【计算机网络】——UDP编程、TCP和UDP的区别

    技术2025-12-29  7

    文章目录

    1、UDP服务特点2、UDP网络编程2.1UDP程序设计常用函数2.2编程框架及代码实现 3、TCP与UDP的区别3.1字节流和数据报服务的区别3.2优缺点对比

    1、UDP服务特点

    在上一篇的博文中,我们详细的介绍了TCP服务的特性和编程流程。还是一样的思路,我们来分析一下UDP服务吧~ 简单来说,UDP就是无连接的、不可靠的数据报服务

    无连接:相比于TCP,它发送数据之前不需要建立链接。也就是说没有listen和accpet操作。不可靠:没有确认机制,没有重传机制,如果因为网络故障该段无法发到对方,UDP协议层也不会给应用层返回任何错误信息面向数据报:应用层交给UDP多长的报文, UDP原样发送, 既不会拆分, 也不会合并;

    【缺点】不可靠、丢包严重 基于上述的特点,我们可以发现,在网络质量十分不满意的环境下,UDP协议数据包丢失会比较严重。

    【优点】速度快、较安全 但是由于UDP的特性——不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送的时候使用UDP较多。因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。比如我们聊天用的 ICQ 和 QQ 就是使用的 UDP。

    【使用UDP网络发送数据注意事项】

    前提:必须要保证他们在同一个局域网中,要在一个网段才行,跨网就不能直接通讯;每个分组都携带完整的目的地址;

    2、UDP网络编程

    2.1UDP程序设计常用函数

    1、sendto()函数

    #include <sys/types.h> #include <sys/socket.h> 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:发送缓冲区的大小,单位是字节;flags:填0即可;dest_addr:指向接收数据的主机地址信息的结构体,也就是该参数指定数据要发送到哪个主机哪个进程;addrlen:表示第五个参数所指向内容的长度;返回值:成功返回发送成功的数据长度,失败返回 -1。

    截取代码实现如下:

    struct sockaddr_in ser; memset(&ser, 0, sizeof(ser)); ser.sin_family = AF_INET; ser.sin_port = htons(6000); ser.sin_addr.s_addr = inet_addr("127.0.0.1"); int res = sendto(sockfd, data, strlen(data) - 1, 0, (struct sockaddr*)&ser, sizeof(ser)); assert(res != -1);

    2、recvfrom()函数

    #include <sys/types.h> #include <sys/socket.h> ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

    【功能】接收UDP数据,并将源地址信息保存在from指向的结构中 【参数】 前面四个参数和sendto函数一样,在这里就不再赘述。

    src_addr:指向发送数据的主机地址信息的结构体,也就是我们可以从该参数获取到数据是谁发出的;addrlen:表示第五个参数所指向内容的长度的地址;

    截取代码实现如下:

    char buff[128] = {0}; struct sockaddr_in cli; socklen_t len = sizeof(cli); int n = recvfrom(sockfd, buff, 127, 0, (struct sockaddr*)&cli, &len);

    3、注意事项

    recvfrom和sendto系统调用也可以用于面向连接的socket的数据读写,只需要把最后两个参数都设置为NULL以忽略发送端/接收端的socket地址(因为双反已经建立了连接,所以已经知道其socket地址了)。因为UDP无连接的特点,只能是客户端通过主动sendto给服务器发送数据同时将客户端的地址信息带过去,这时候服务器才能给其回馈数据。所以,客户端和服务器通讯必须先调用sendto。

    2.2编程框架及代码实现

    1、基本框架 和TCP不同,他是无连接的,所以没有监听连接listen和接收连接accept的过程。在作为服务器的被动方和作为客户端的主动方他们所完成的流程图如下: 根据以上的流程图可以得出伪代码如下: 2、代码实现 【服务端】

    #include <stdio.h> #include <stdlib.h> #include <assert.h> #include <unistd.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <netinet/in.h> int main() { int sockfd = socket(AF_INET, SOCK_DGRAM, 0); assert(-1 != sockfd); struct sockaddr_in ser; memset(&ser, 0, sizeof(ser)); ser.sin_family = AF_INET; ser.sin_port = htons(6500); ser.sin_addr.s_addr = inet_addr("127.0.0.1"); int res = bind(sockfd, (struct sockaddr*)&ser, sizeof(ser)); assert(res != -1); while(1) { char buff[128] = {0}; struct sockaddr_in cli; socklen_t len = sizeof(cli); int n = recvfrom(sockfd, buff, 127, 0, (struct sockaddr*)&cli, &len); if(n <= 0) { printf("recvfrom error\n"); continue; } printf("%s:%d --> %s\n", inet_ntoa(cli.sin_addr), ntohs(cli.sin_port),buff); int res = sendto(sockfd, "OK", 2, 0, (struct sockaddr*)&cli, len); if(res <= 0) { printf("sendto error\n"); continue; } close(sockfd); exit(0); } }

    【客户端】

    #include <stdio.h> #include <stdlib.h> #include <assert.h> #include <unistd.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <netinet/in.h> int main() { int sockfd = socket(AF_INET, SOCK_DGRAM, 0); assert(-1 != sockfd); struct sockaddr_in ser; memset(&ser, 0, sizeof(ser)); ser.sin_family = AF_INET; ser.sin_port = htons(6000); ser.sin_addr.s_addr = inet_addr("127.0.0.1"); while(1) { printf("please input: "); char data[128] = {0}; fgets(data, 128, stdin); if(strncmp(data, "bye", 3) == 0) { break; } int res = sendto(sockfd, data, strlen(data) - 1, 0, (struct sockaddr*)&ser, sizeof(ser)); assert(res != -1); memset(data,0,128); int n = recvfrom(sockfd, data, 127, 0, NULL, NULL); assert(n != -1); printf("recvfrom data:%s\n", data); } close(sockfd); exit(0); }

    测试结果

    3、TCP与UDP的区别

    3.1字节流和数据报服务的区别

    我们之前在将TCP和UDP的特点的时候,我们可以明确的知道TCP就是一种字节流服务,而UDP是一种数据报服务,但是他们具体的含义和区别是什么呢?下面,我们通过代码实践来研究一下。

    1、字节流服务 当我们改变代码中接收数据的个数为5的时候,我们运行程序,当客户端向服务器接收数据的结果如下图所示: 从上面的运行结果,我们可以清楚的看见,当我们传送的数据超过5字节的时候,服务器端收到的数据不是一次性接收的。 其实这就是我们所说的字节流服务,它的数据传输具体流程如下图所示: 从上面的数据传输流程,我们可以总结出字节流服务的特点,也可以看出流就是数据的发送和接收是无法区分的。

    发送端send的次数与接收端recv的次数不相等发送端send的次数与网络层封装的TCP报文段的个数也不相等接收端recv如果一次没有将数据读取完成,则下次recv会继续读取后续的数据

    【注意】——粘包问题 1、产生原因 发送端需要等缓冲区满才发送出去,造成粘包。或者接收方不及时接收缓冲区的包,造成多个包接收 2、解决方法

    定长数据流:服务器客户端提前协商,每个消息定长,不足的空白字符补足特殊结束符:双方协商定义一个特殊的分隔符号 比如@ # KaTeX parse error: Expected group after '_' at position 1: _̲等 只要没有发送分隔符就意味着一条数据没有结束协议:相对最成熟额数据传递方式,由服务器开发者提供固定格式的协议标准,双方都按照协议进行发送接收数据的。

    详细请参考博文 如何解决TCP通信中的粘包问题? 2、数据报服务 当我们改变UDP代码中接收数据的个数为5的时候,我们运行程序,当客户端向服务器接收数据的结果如下图所示: 从运行结果,我们可以看出会有一部分数据的丢失,并不是完成了数据的全部接收。这是为什么呢?其实就是我们数据报服务的特点。下图表示的就是数据报服务传输数据的过程 从上面的传输过程,我们就可以总结出数据报服务传输数据的特点:

    发送方sendto的次数和接收方recvfrom的次数相等 举个栗子来说:如果发送端调用一次sendto, 发送100个字节, 那么接收端也必须调用对应的一次recvfrom, 接收100个字节; 而不能循环调用10次recvfrom, 每次接收10个字节发送方sendto的次数与网络底层封装的UDP报文段的个数相等如果接收方一次recvfrom没有将UDP报文段中的数据接收完,则此报文段中剩余的数据会被丢弃。

    【注意】

    UDP没有真正意义上的发送缓冲区. 调用sendto会直接交给内核, 由内核将数据传给网络层协议进行后续的传输动作;UDP具有接收缓冲区 但是这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一致; 如果缓冲区满了, 再到达的UDP数据就会被丢弃;基于UDP的应用层协议 协议名称协议作用NFS网络文件协议TFTP简单的文件传输协议DHCP动态主机配置协议BOOTP启动协议(用于无盘设备启动)DNS域名解析协议

    3.2优缺点对比

    1、TCP优缺点 【优点】 可靠、稳定。它体现在TCP在传递数据之前,会有三次握手来建立连接;在数据传递时,采用校验和、序列号、确认应答、超时重发、流量控制、拥塞控制,为了提高性能,还采用了滑动窗口、延迟应答和捎带应答等机制;在数据传完后,会断开连接以节约系统资源。 【缺点】

    速度慢:因为TCP在传递数据之前,要先建立连接,这会消耗时间;在数据传递时,确认机制、重传机制、拥塞控制机制等都会消耗大量的时间效率低、占用系统资源多:要在每台设备上维护所有的传输连接,每个连接都会占用系统的CPU、内存等资源易被攻击:TCP有确认机制、三次握手机制,这导致TCP容易受到DOS、DDOS、CC等攻击。收到STN洪水攻击,是因为使用 TCP的时候服务器端需要listen,这时需要设置backlog。

    2、UDP优缺点

    【优点】

    运行速度快:因为 UDP连接没有TCP的三次握手、确认应答、超时重发、流量控制、拥塞控制等机制,而且UDP是一个无状态的传输协议,所以它在传递数据时非常快。较安全:因为没有TCP的那些机制,UDP较TCP被攻击者利用的漏洞就会少一些。但UDP也是无法避免攻击的,比如:UDP Flood攻击等。

    【缺点】 不可靠,不稳定:因为UDP没有TCP那些可靠的机制,在数据传递时,如果网络质量不好,就会很容易丢包。

    总结一下:

    角度TCPUDP连接面向连接无连接可靠性可靠服务,通过校验和、序号确认号、超时重传、滑动窗口机制保证报文无差错、不丢失、不重复、按序到达尽最大努力交付,不保证可靠性效率TCP因为机制复杂,所以实时性,工作效率低UDP机制简单,所以实时性、工作效率高,使用于实时性要求比较高的通信或广播通信等场景传输场景只能用于一对一通信可用于一对一,一对多,多对一,多对多等传输场景资源对系统资源要求多,因为要管理连接,可靠传输对系统资源要求多,因为要管理连接,可靠传输内存开销TCP有20字节的首部开销,大UDP只有8字节的首部开销。
    Processed: 0.016, SQL: 9