跳到主要内容

UDP socket 编程实践

·281 字·2 分钟

UDP 是面向非连接的,如果通讯双方都在局域网中,服务器端和客户端没有区别,如果是局域网内的主机与公网上的主机通讯,由于 NAT 地址转换协议的作用,必须由局域网内的主机主动向公网的主句发送数据,公网的主机作为服务器端,必须接收客户端的数据后,解析出源 IP 和端口,再反向发送,实现双向通讯。下面是一个简单的 Demo 。

服务器端:

    // server.c
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <string.h>
    
    #define SERVER_PORT 6789
    #define CPU_PORT 9009
    #define BUFF_LEN 1024
    
    int main(int argc, char* argv[])
    {
        int server_fd, count;
        struct sockaddr_in ser_addr; 
        struct sockaddr_in src_addr;
        socklen_t len;
        char buf[BUFF_LEN];
    
        server_fd = socket(AF_INET, SOCK_DGRAM, 0); //IPV4,UDP
    
        memset(&ser_addr, 0, sizeof(ser_addr));
        ser_addr.sin_family = AF_INET;
        ser_addr.sin_addr.s_addr = htonl(INADDR_ANY); // any ip
        ser_addr.sin_port = htons(SERVER_PORT);  // server port
    
        bind(server_fd, (struct sockaddr*)&ser_addr, sizeof(ser_addr));
    
        while(1)
        {
            // recv
            memset(buf, 0, BUFF_LEN);
            len = sizeof(src_addr);
            count = recvfrom(server_fd, buf, BUFF_LEN, 0, (struct sockaddr*)&src_addr, &len);  //block
            if(count == -1)
            {
                printf("recieve data fail!\n");
                return 0;
            }
            printf("server recv from %s:%d : %s\n",inet_ntoa(src_addr.sin_addr),ntohs(src_addr.sin_port),buf);
    
            // send
            memset(buf, 0, BUFF_LEN);
            sprintf(buf, "Server have recieved %d bytes data!", count);
            printf("server send : %s\n\n",buf);
            // send to src_addr
            sendto(server_fd, buf, BUFF_LEN, 0, (struct sockaddr*)&src_addr, len);
        }
    
        close(server_fd);
        return 0;
    }

客户端:

    // cpu.c
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <string.h>
    
    #define SERVER_IP "118.89.16.24"
    #define SERVER_PORT 6789
    #define CPU_PORT 9009
    #define BUFF_LEN 1024
    
    int main(int argc, char* argv[])
    {
        int cpu_fd;
        struct sockaddr_in ser_addr;
        struct sockaddr_in src_addr;
        struct sockaddr_in my_addr;
        socklen_t len;
        char buf[BUFF_LEN] = "cpu msg!";
    
        cpu_fd = socket(AF_INET, SOCK_DGRAM, 0); //IPV4,UDP
    
        memset(&my_addr, 0, sizeof(my_addr));
        my_addr.sin_family = AF_INET;
        my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // any ip
        my_addr.sin_port = htons(CPU_PORT);  // server port
        bind(cpu_fd, (struct sockaddr*)&my_addr, sizeof(my_addr));
    
        memset(&ser_addr, 0, sizeof(ser_addr));
        ser_addr.sin_family = AF_INET;
        ser_addr.sin_addr.s_addr = inet_addr(SERVER_IP); 
        ser_addr.sin_port = htons(SERVER_PORT);
    
        len = sizeof(ser_addr);
        printf("CPU send : %s\n",buf);  
        sendto(cpu_fd, buf, BUFF_LEN, 0, (struct sockaddr*)&ser_addr, len);
    
        memset(buf, 0, BUFF_LEN);
        recvfrom(cpu_fd, buf, BUFF_LEN, 0, (struct sockaddr*)&src_addr, &len);  //recv msg from server
        printf("CPU recv from %s:%d : %s\n",inet_ntoa(src_addr.sin_addr),ntohs(src_addr.sin_port),buf);
    
        close(cpu_fd);
        return 0;
    }