UDP通信机制详解

UDP通信机制详解UDP 通信机制详解 以及基于 UDP 的客户端服务端实现

大家好,欢迎来到IT知识分享网。

在这里插入图片描述

欢迎关注博主 Mindtechnist 或加入【Linux C/C++/Python社区】一起学习和分享Linux、C、C++、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和技术。



专栏:《Linux从小白到大神》《网络编程》


1. UDP通信流程

前面介绍了TCP,TCP是面向连接的、安全的、流式传输协议。UDP是面向无连接的、不安全的、报式传输协议。UDP通信流程如下:

  • 服务器端:
      • 第二个参数使用SOCK_DGRAM,表示报式协议,即UDP。TCP使用的是SOCK_STREAM。
    • 绑定IP和端口:bind
      • fd
      • struct sockaddr —— 服务器
    • 通信
      • 接收数据:recvfrom
        ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen); 

        同accept的第2、3个参数使用方法相同。

        • sockfd:文件描述符
        • buf:接收数据缓冲区
        • len:buf的最大容量
        • flags:0
        • src_addr:另一端的IP和端口, 传出参数
        • addrlen:传入传出参数
      • 发送数据: sendto
        ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); 
        • sockfd:socket函数创建出来的
        • buf:存储发送的数据
        • len:发送的数据的长度,注意是发送数据的大小,而不是buf的大小 strlen()。
        • flags:0
        • dest_addr:另一端的IP和端口
        • addrlen:dest_addr长度
    • UDP服务器端:需要一个套接字, 通信

    创建套接字 – socket

  • 客户端:
    • 通信
          • 存储服务器的IP和端口

        需要先准备好一个结构体:struct sockaddr_in

      • 接收数据:recvform

      发送数据:sendto,如果发送的数据太大,sendto会调用失败,UDP报文的长度是有上限的。

    创建一个用于通信的套接字:socket

  • udp的数据是不安全的, 容易丢包
      • 只能丢全部,不存在只丢一部分的情况
    • 优点: 效率高

    丢包, 丢全部还一部分?

UDP通信流程示意图如下

在这里插入图片描述

2. UDP客户端与服务端实现

server

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <arpa/inet.h> int main(int argc, const char* argv[]) { 
     // 创建套接字 int fd = socket(AF_INET, SOCK_DGRAM, 0); if(fd == -1) { 
     perror("socket error"); exit(1); } // fd绑定本地的IP和端口 struct sockaddr_in serv; memset(&serv, 0, sizeof(serv)); serv.sin_family = AF_INET; serv.sin_port = htons(8765); serv.sin_addr.s_addr = htonl(INADDR_ANY); int ret = bind(fd, (struct sockaddr*)&serv, sizeof(serv)); if(ret == -1) { 
     perror("bind error"); exit(1); } struct sockaddr_in client; socklen_t cli_len = sizeof(client); // 通信 char buf[1024] = { 
    0}; while(1) { 
     int recvlen = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr*)&client, &cli_len); if(recvlen == -1) { 
     perror("recvform error"); exit(1); } printf("recv buf: %s\n", buf); char ip[64] = { 
    0}; printf("New Client IP: %s, Port: %d\n", inet_ntop(AF_INET, &client.sin_addr.s_addr, ip, sizeof(ip)), ntohs(client.sin_port)); // 给客户端发送数据 sendto(fd, buf, strlen(buf)+1, 0, (struct sockaddr*)&client, sizeof(client)); } close(fd); return 0; } 

client

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <arpa/inet.h> int main(int argc, const char* argv[]) { 
     // create socket int fd = socket(AF_INET, SOCK_DGRAM, 0); if(fd == -1) { 
     perror("socket error"); exit(1); } // 初始化服务器的IP和端口 struct sockaddr_in serv; memset(&serv, 0, sizeof(serv)); serv.sin_family = AF_INET; serv.sin_port = htons(8765); inet_pton(AF_INET, "127.0.0.1", &serv.sin_addr.s_addr); //把点分十进制字符串 "127.0.0.1" 转成整形,并存到&serv.sin_addr.s_addr中 // 通信 while(1) { 
     char buf[1024] = { 
    0}; fgets(buf, sizeof(buf), stdin); // 数据的发送 - server - IP port sendto(fd, buf, strlen(buf)+1, 0, (struct sockaddr*)&serv, sizeof(serv)); // 等待服务器发送数据过来 recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL); //服务器的IP和port已经在在初始化的时候知道了,传NULL即可 printf("recv buf: %s\n", buf); } close(fd); return 0; } 

3. 心跳包

UDP是无连接的通信协议,那么如何去判断客户端和服务端是否处于连接状态呢?这就是心跳机制:

  • 心跳机制
    • 不会携带大量的数据
    • 每隔一定时间 服务器 → 客户端 / 客户端→服务器 发送一个数据包
  • 心跳包看成一个协议
    • 应用层协议
  • 判断网络是否断开
    • 有多个连续的心跳包没收到或没有回复
    • 关闭通信的套接字
  • 重连
    • 重新初始套接字
    • 继续发送心跳包
  • 乒乓包
    • 比心跳包携带的数据多一些
    • 除了知道连接是否存在,还能获取一些信息

如何理解心跳包呢——比如说,坐火车过隧道的时候,微信会提示服务器已断开连接,通过隧道后,微信会自己连上服务器。微信是如何知道和服务器断开连接了呢?就是通过心跳包机制。

比如,提前约定好,每隔多少秒客服端向服务器发1,如果服务器收到1,则回复客户端2,客户端收到2再发1,如此循环。如果客户端发送完1没有收到服务器回复的2,那么客户端将会再次发送1,测试几次如果依然没有回复,那么客户端会提示“服务器已断开连接”。

在这里插入图片描述

心跳包只能判断有没有连接,而乒乓包可以携带一些数据。

乒乓包——比如微信,如果有人给你发消息,或者有人发布朋友圈,给你点赞,都会有一个小红点提示,那么你的手机微信是怎么知道有人给你点赞,有人发朋友圈的呢?就是通过乒乓包不停的去询问。但是乒乓包也不是能携带所有数据,我们看到小红点,得点进去,然后手机客户端向服务器请求数据才能看到具体发了啥内容,评论了啥内容。心跳包只能判断是否连接,乒乓包可以携带少量提示信息。

4. TCP/UDP应用场景

  • TCP使用场景
      • 登录数据的传输 —— 比如用户名密码
      • 文件传输
    • HTTP协议
      • 传输层协议 —— TCP

    对数据安全性要求高的时候

  • UDP使用场景
      • 视频聊天、直播
      • 通话
    • 有实力的大公司
      • 使用UDP
      • 在应用层自定义协议来做数据校验,既保证了传输效率,又保证了不丢数据。

    效率高 —— 实时性要求比较高


在这里插入图片描述
在这里插入图片描述


免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/121776.html

(0)
上一篇 2025-10-21 16:10
下一篇 2025-10-21 16:20

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信