• Socket tips: UDP Echo service


    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <time.h>
    
    #define BUFFER_LENGTH 1024
    
    void ExitWithMessage(const int errorCode, const char * errorMessage)
    {
        fprintf(stderr, "
    
    Error Msg  : %s
    ", errorMessage);
        fprintf(stderr, "Error Code : 0x%X
    ", errorCode);
        fprintf(stderr, "Location   : %s: %d
    
    ", __FILE__, __LINE__);
    
        exit(errorCode);
    }
    
    void PrintIPv4(unsigned long ipvalue, FILE * stream)
    {
        uint8_t a;
        uint8_t b;
        uint8_t c;
        uint8_t d;
    
        a = ipvalue >> 24;
    
        ipvalue -= a * 0x01000000;
        b = ipvalue >> 16;
    
        ipvalue -= b * 0x00010000;
        c = ipvalue >> 8;
    
        ipvalue -= c * 0100000100;
        d = ipvalue;
    
        fprintf(stream, "%d.%d.%d.%d", d, c, b, a);
    }
    
    void PrintSocketAddress(const struct sockaddr * address, FILE * stream)
    {
        struct in_addr ip4addr;
        in_port_t port;
    
        struct sockaddr_in * ipv4Address;
    
        if(address == NULL || stream == NULL)
        {
            return;
        }
    
        //printf("sa_family: %d
    ", address->sa_family);
    
        switch(address->sa_family)
        {
            case AF_INET:
    
                fputs("[IPv4] ", stream);
    
                ipv4Address = (struct sockaddr_in *)address;
                ip4addr = ipv4Address->sin_addr;
    
                port = ntohs(ipv4Address->sin_port);
    
                //fprintf(stream, "ip4addr.s_addr: %X
    ", ip4addr.s_addr);
                PrintIPv4(ip4addr.s_addr, stream);
                fprintf(stream, " : %d", port);
    
                break;
            case AF_INET6:
    
                fputs("[IPv6] ", stream);
    
                break;
            default:
                fputs("[unknown type]", stream);
                return;
        }
    }
    
    int main(int argc, char * argv[])
    {
        char * server;
        char * serverPort;
        char * echoString;
        size_t echoStringLength;
    
        struct addrinfo addrCriteria;
        struct addrinfo *serverAddr;
        int socketHandle;
        int returnValue;
        ssize_t receivedBytesCount;
        ssize_t sendBytesCount;
        struct sockaddr_storage responseAddr;
        socklen_t responseAddrLen = sizeof(struct sockaddr);
        char buffer[BUFFER_LENGTH + 1];
    	
    	int broadcastPermission = 1;
    
        if(argc < 3 || argc > 4)
        {
            ExitWithMessage(1, "Parameters: <Server_IPv4> <Server_Port> <Message>");
        }
    
        server = argv[1];
        serverPort = argv[2];
        echoString = argv[3];
        echoStringLength = strlen(echoString);
    
        if(echoStringLength >= BUFFER_LENGTH)
        {
            ExitWithMessage(2, "Message is too long.");
        }
    
        memset(&addrCriteria, 0, sizeof(struct addrinfo));
    
        addrCriteria.ai_family = AF_UNSPEC; // Any address family
        addrCriteria.ai_flags = AI_PASSIVE; // Accept on any address/port
        addrCriteria.ai_socktype = SOCK_DGRAM; // only datagram socket
        addrCriteria.ai_protocol = IPPROTO_UDP; // only UDP socket
    
        returnValue = getaddrinfo(server, serverPort, &addrCriteria, &serverAddr);
        if(returnValue != 0)
        {
            fprintf(stderr, "getaddrinfo() failed.
    ");
            ExitWithMessage(returnValue, gai_strerror(returnValue));
        }
    
        // Create a datagram/UDP socket
        socketHandle = socket(serverAddr->ai_family, serverAddr->ai_socktype, serverAddr->ai_protocol);
        if(socketHandle < 0)
        {
            fprintf(stderr, "socket() failed.
    ");
            ExitWithMessage(socketHandle, gai_strerror(socketHandle));
        }
    	
    	// Set socket to be allowed broadcast
    	
    	returnValue = setsockopt(
    		socketHandle, SOL_SOCKET, 
    		SO_BROADCAST, 
    		(void *) &broadcastPermission, 
    		sizeof(broadcastPermission));
    		
    	if(returnValue != 0)
        {
            fprintf(stderr, "setsockopt() failed.
    ");
            ExitWithMessage(returnValue, gai_strerror(returnValue));
        }
    
        sendBytesCount = sendto(socketHandle, echoString, echoStringLength, 0, serverAddr->ai_addr, serverAddr->ai_addrlen);
        if(sendBytesCount < 0)
        {
            fprintf(stderr, "sendto() failed.
    ");
            ExitWithMessage(sendBytesCount, gai_strerror(sendBytesCount));
        }
    
        // Receive a response
    
        receivedBytesCount = recvfrom(
    		socketHandle,
    		buffer,
    		BUFFER_LENGTH,
    		0,
    		(struct sockaddr *)&responseAddr,
    		&responseAddrLen);
    
        if(receivedBytesCount < 0)
        {
            fprintf(stderr, "recvfrom() failed.
    ");
            ExitWithMessage(receivedBytesCount, gai_strerror(receivedBytesCount));
        }
    
    	fputs("Server address: ", stdout);
        PrintSocketAddress((struct sockaddr *)&responseAddr, stdout);
    
        buffer[receivedBytesCount] = '';
        printf("
    Response: %s
    ", buffer);
    
    	freeaddrinfo(serverAddr);
    
        return 0;
    }
    

    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    犯错记录(一)
    BullseyeCoverage:代码覆盖率。
    测试工具:insure++
    C++ 常见容器
    linux修改rm指令执行(数据安全)
    C++细节系列(零):零散记录
    vim中使用gdb。
    vim自动补全文章搜集
    排序算法的个人心得体会。
    面向对象的三个特征。
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4907468.html
Copyright © 2020-2023  润新知