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

本文详细介绍了UDP通信的基本流程,包括服务器端和客户端的实现,并通过示例代码展示了UDP服务器和客户端的创建、数据收发。接着,讨论了广播与组播的区别,广播主要用于局域网内的多台计算机通信,而组播则适用于更广泛的网络环境。最后,给出了广播和组播的代码实现,展示了如何设置广播属性和加入多播组进行通信。
摘要由CSDN通过智能技术生成

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....%d\n", num++);
        // 发送数据
        sendto(fd, sendBuf, strlen(sendBuf) + 1, 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr));
        printf("广播的数据:%s\n", 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 : %s\n", 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....%d\n", num++);
        // 发送数据
        sendto(fd, sendBuf, strlen(sendBuf) + 1, 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr));
        printf("组播的数据:%s\n", 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 : %s\n", buf);

    }

    close(fd);
    return 0;
}
  • 8
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Linux网络编程中的TCP和UDP是两种常见的传输协议。 TCP(Transmission Control Protocol)是一种基于连接的可靠传输协议。它提供了面向连接、可靠的数据传输服务。在TCP通信中,数据被分割成小的数据块,通过TCP连接按序传输,并且保证数据的可靠性,即使在网络拥塞或数据丢失的情况下也能重新传输丢失的数据。TCP适用于对可靠性要求较高的应用程序,如文件传输、电子邮件和网页浏览。 UDP(User Datagram Protocol)是一种无连接的不可靠传输协议。它提供了一种无序、不可靠的数据传输服务。在UDP通信中,数据以数据包(也称为数据报)的形式发送,不进行连接建立和断开,也不保证数据的可靠性和按序传输。UDP适用于对实时性要求较高、对数据可靠性要求较低的应用程序,如音视频流媒体、在线游戏等。 在Linux中进行TCP和UDP网络编程可以使用Socket API。该API提供了一组函数和数据结构,用于创建套接字(socket)、绑定(bind)套接字到特定的IP地址和端口、监听(listen)连接请求、接受(accept)连接、建立连接(connect)、发送(send)和接收(receive)数据等操作。 你可以使用C语言或其他支持Socket API的编程语言来进行Linux网络编程,通过调用Socket API提供的函数来实现TCP或UDP通信。在编程过程中,你需要了解TCP和UDP的特点、使用套接字创建相应的连接类型、发送和接收数据的方式等。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值