Linux网络编程——UDP通信 代码实现

UDP通信

1. UDP

服务器端、客户端实现过程-来源牛客
代码实现流程如下所示

UDP通信过程
    //服务器端
        1. socket() 创建套接字
        2. bind() 绑定套接字
    与TCP区别开来,没有listen()accept()建立连接的过程
        3. 通信 recvfrom() sendto()
        4. close
    //客户端
        1. socket() 创建套接字
    与TCP区别开来,没有connect()建立连接的过程
        2. 通信 sendto() recvfrom()
        3. close()
//UDP 服务器端 - udpServer.cpp
int main(){

    int fd = socket(PF_INET, SOCK_DGRAM, 0);
    //注意SOCK_DGRAM  TCP对应的第二个参数是SOCK_STREAM
    if(fd == -1){
        perror("udpServer.cpp socket() errors");
        exit(-1);
    }
    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    serverAddr.sin_port = htons(8888);
    int ret = bind(fd, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
    if(ret == -1){
        perror("udpServer.cpp bind() errors");
        exit(-1);
    }
    while(1){
        char buf[BUFSIZ];
        char ipBuf[16];
        struct sockaddr_in clientAddr;
        socklen_t size = sizeof(clientAddr);

        int len = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *) &clientAddr, &size);
        cout << "client IP = " << inet_ntop(AF_INET, &clientAddr.sin_addr.s_addr, ipBuf, sizeof(ipBuf))
                        << "client PORT = " << ntohs(clientAddr.sin_port) << endl;
        cout << "server recv : " << buf << endl;
        sendto(fd, buf, strlen(buf) + 1, 0, (struct sockaddr *) &clientAddr, sizeof(clientAddr));
    }
    
    close(fd);
    return 0;
}
//UDP 客户端 - udpClient.cpp 
int main() {

    int fd = socket(PF_INET, SOCK_DGRAM, 0);
    if(fd == -1) {
        perror("socket");
        exit(-1);
    }   
    struct sockaddr_in clientAddr;
    clientAddr.sin_family = AF_INET;
    clientAddr.sin_port = htons(8888);
    inet_pton(AF_INET, "127.0.0.1", &clientAddr.sin_addr.s_addr);
    int num = 0;
    while(1) {
        char buf[BUFSIZ];
        sprintf(buf, "hello , i am client %d n", num++);
        sendto(fd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&clientAddr, sizeof(clientAddr));

        int len = recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL);
        cout << "client recv : " << buf << endl;

        sleep(1);
    }

    close(fd);
    return 0;
}

2. 广播与组播

先讲讲 广播 与后面要实现的 组播(多播) 的区别

广播:向子网中的多台计算机发送消息。
	1.特征:
		IP地址由网络号+主机号构成,而广播则是主机标识部分全为1,即必须满足 *.*.*.255结尾
	2.应用:
		A.只能在局域网中使用;
		B.客户端需要绑定服务使用的端口,才能收到广播消息。
	3.实现:
		设置广播属性的函数setsockport()
组播(多播):
	1.联系:
		A.单播地址标识单个IP接口;
		B.广播地址表示某个子网的所有IP接口;
		C.多播地址标识一组IP接口,是前两种的折中方案。
	2.应用:
		A.既可以用于局域网,又可以用于跨广域网;
		B.客户端需要加入多播组,才能接受到多播的数据。

广播图
广播图-来源牛客
组播图(多播)
多播图-来自牛客
广播代码实现流程如下所示

广播通信
    //服务器端
        1. socket() 创建套接字
        2. setsockpot()设置广播属性
        3. 创建一个广播的地址 inet_pton
        4. 通信 recvfrom() sendto()
        5. close
    //客户端
        1. socket() 创建套接字
        2. 客户端绑定本地的IP和PORT
        3. 通信 sendto() recvfrom()
        4. close()

广播代码实现如下所示

//广播 服务器端
int main() {
    int fd = socket(PF_INET, SOCK_DGRAM, 0);
    if(fd == -1) {
        perror("socket");
        exit(-1);
    }   

    int op = 1;
    setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &op, sizeof(op));
    
    struct sockaddr_in cliaddr;
    cliaddr.sin_family = AF_INET;
    cliaddr.sin_port = htons(9999);
    inet_pton(AF_INET, "172.25.191.255", &cliaddr.sin_addr.s_addr);

    int num = 0;
    while(1) {
       
        char sendBuf[128];
        sprintf(sendBuf, "hello, client....%dn", num++);
        // 发送数据
        sendto(fd, sendBuf, strlen(sendBuf) + 1, 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr));
        printf("广播的数据:%sn", sendBuf);
        sleep(1);
    }

    close(fd);
    return 0;
}
//广播 客户端端
int main() {

    int fd = socket(PF_INET, SOCK_DGRAM, 0);
    if(fd == -1) {
        perror("socket");
        exit(-1);
    }   

    struct in_addr in;
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(9999);
    addr.sin_addr.s_addr = INADDR_ANY;

    int ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
    if(ret == -1) {
        perror("bind");
        exit(-1);
    }

    while(1) {
        
        char buf[128];
        int num = recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL);
        printf("server say : %sn", buf);

    }

    close(fd);
    return 0;
}

组播实现流程如下所示:

多播通信
    //服务器端
        1. socket() 创建套接字
        2. setsockpot()设置多播属性
        3. 初始化客户端的地址信息 IP PORT
        4. 通信 recvfrom() sendto()
        5. close
    //客户端
        1. socket() 创建套接字
        2. 客户端bind绑定本地的IP和PORT
        3. setsockopt加入多播组
        4. 通信 sendto() recvfrom()
        5. close()
//多播服务器端
int main() {

    // 1.创建一个通信的socket
    int fd = socket(PF_INET, SOCK_DGRAM, 0);
    if(fd == -1) {
        perror("socket");
        exit(-1);
    }   

    // 2.设置多播的属性,设置外出接口
    struct in_addr imr_multiaddr;
    // 初始化多播地址
    inet_pton(AF_INET, "239.0.0.10", &imr_multiaddr.s_addr);
    setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &imr_multiaddr, sizeof(imr_multiaddr));
    
    // 3.初始化客户端的地址信息
    struct sockaddr_in cliaddr;
    cliaddr.sin_family = AF_INET;
    cliaddr.sin_port = htons(9999);
    inet_pton(AF_INET, "239.0.0.10", &cliaddr.sin_addr.s_addr);

    // 3.通信
    int num = 0;
    while(1) {
       
        char sendBuf[128];
        sprintf(sendBuf, "hello, client....%dn", num++);
        // 发送数据
        sendto(fd, sendBuf, strlen(sendBuf) + 1, 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr));
        printf("组播的数据:%sn", sendBuf);
        sleep(1);
    }

    close(fd);
    return 0;
}
//多播客户端
int main() {

    // 1.创建一个通信的socket
    int fd = socket(PF_INET, SOCK_DGRAM, 0);
    if(fd == -1) {
        perror("socket");
        exit(-1);
    }   

    struct in_addr in;
    // 2.客户端绑定本地的IP和端口
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(9999);
    addr.sin_addr.s_addr = INADDR_ANY;

    int ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
    if(ret == -1) {
        perror("bind");
        exit(-1);
    }

    struct ip_mreq op;
    inet_pton(AF_INET, "239.0.0.10", &op.imr_multiaddr.s_addr);
    op.imr_interface.s_addr = INADDR_ANY;

    // 加入到多播组
    setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &op, sizeof(op));

    // 3.通信
    while(1) {
        
        char buf[128];
        // 接收数据
        int num = recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL);
        printf("server say : %sn", buf);

    }

    close(fd);
    return 0;
}

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>