资讯详情

资讯详情

第十二节 UDP协议和TCP协议

一、UDP协议和TCP协议对比TCP 和 UDP 是传输层最重要的两个协议TCP 是打电话​——先接通、按顺序说、确认对方听清了UDP 是寄明信片​——直接扔出去快但不保证一定送达、也不保证先后顺序。对比TCPUDP连接性面向连接三次握手建立、四次挥手释放无连接直接发送可靠性可靠序号确认超时重传校验不可靠尽最大努力交付出错即丢传输单位字节流面向报文边界不保留数据报保留报文边界一次发一次收有序性保证按序到达乱序重排不保证顺序开销头部 20~60 字节且需维护连接状态头部固定 8 字节状态机极简速度/适用慢、稳文件、网页、邮件快、轻直播、语音、DNS、游戏通信方式一对一一对一 / 一对多 / 多对多首部字段源端口、目的端口、序号、确认号、数据偏移、标志位、窗口、校验和、紧急指针、选项源端口、目的端口、长度、校验和注意TCP 首部字段多是因为要可靠UDP 只有 4 个字段就是够用就行。UDP 校验和是唯一的差错检测手段而且是可选的IPv4 下可为 0 表示不校验二、IP地址的特殊性额外补充2.1、本质就是一个4字节的无符号整数ntohl,htonl进行转换即可htonl、ntohl 是网络编程里最常被随手写下的两个函数搞懂它们只需要抓住一件事不同 CPU 在内存里存放多字节整数的顺序不一样。hhost主机字节序本机CPU的顺序nnetwork网络字节序TCP/IP规定大端高位字节在前tto/llong按32位处理所以 htonl 主机序 → 网络序发送前转ntohl 网络序 → 主机序接收后转。头文件Linux/macOS 是 arpa/inet.hWindows 是 winsock2.h并链接 ws2_32.lib。例如struct sockaddr_in addr; memset(addr, 0, sizeof(addr)); addr.sin_family AF_INET; addr.sin_port htons(8080); /* 16 位端口 */ addr.sin_addr.s_addr htonl(INADDR_ANY); /* 32 位地址 */ bind(sockfd, (struct sockaddr *)addr, sizeof(addr)); /* 收数据时反过来用 */ printf(peer port %d\n, ntohs(peer.sin_port));注意①它返回新值不就地修改。必须写成 port ntohs(p)ntohs(p); 什么也没干。②大端机上它是空操作。在本身就是大端的平台上部分 ARM/MIPS 大端模式编译后一条指令都不生成所以我的机器是小端绝不能成为省略它的理由——代码要能跨平台跑。③单字节不用转。char/uint8_t 数组没有字节序问题IP 的点分四段本来就按顺序存。④它只转值救不了混乱的缓冲区。如果把结构体或大块 buffer 直接 send 过去对齐、填充、字段顺序的问题 htonl 一个都解决不了那是序列化的问题。⑤现代写法更清楚inet_pton() / inet_ntop() 处理字符串与二进制地址互转内部已管好字节序比老的 inet_addr 好后者返回值还得手动 htonl 而且无法报错POSIX.1-2008 还提供了htobe32/be32toh/htobe16/be16tohhtonl本质上就是htobe32的别名——名字里写明大端可读性更好。2.2、转换IP为了能够更加便于记忆会采用点分十进制字符串进行表示192.168.12.12所以很多时候IP地址的转换并不是给与实际的数字而是一个字符串struct in_addr inet_addrconst char*ipstr将字符串点分十进制IP地址直接转换为网络字节序数字IP地址const char *inet_ntoa(struct in_addr addr)将网络字节序数字IP地址 转换为字符串点分十进制 IP地址inet_ntoa这个接口是非线程安全的const char*inet_ntop(int domain,void* src,char *dst,size_t size);功能将网络字节序整数IP地址转换为字符串IP地址domain:AF_INET,AF_INET6,描述要转换的地址类型src:网络字节序的数据地址dst:转换后的字符串存放空间地址size:dst空间的大小int inet_pton(int dommain,const char*src,void *dst);功能将字符串的IP地址转换为网络字节序IP地址三、UDP通信程序的编写流程3.1、协议特性无连接、不可靠、面向数据报连接本质上是通信双方对于对方的状态维护无连接通信双方不需要管理对方的状态只需要知道对方的地址就可以发送数据不可靠不保证数据安全有序到达对方面向数据报一种块式传输有最大长度限制的传输方式64k-8数据传输算是一种块式传输收发都是以块为单位。UDP固定报头8字节UDP数据传输的时候报文中明确标识了报文长度接收方接收数据时不允许出现半个多多个一次性取出的情况只能逐条获取3.2、UDP协议格式协议格式源端端口对端端口数据报长度校验和数据3.3、UDP编写流程介绍网络通信注意查看网络连接的指令 netstat 可以直接使用netstat -anptu连着一起-a 查看所有-n 不要将地址信息使用知名服务的字符串替代 22---ssh-p 顺便显示该网络连接相关联的进程-t 过滤只显示tcp协议的连接-u 过滤只显示udp协议的连接客户端1、创建套接字int socket(int domain, int type, int protocol);2、为套接字绑定地址信息大多数时候客户都不需要主动绑定地址而是在发送数据的时候由系统找一个空闲的端口——IP进行绑定3、向服务器发送数据struct sockaddr_in srvaddr;srvaddr.sin_familyAF_INET;srvaddr.sin_porthtons();srvaddr.sin_addr.s_addrinet_addr(内网IPv4 地址);socklen_t addrlensizeof(struct sockaddr_in);4、从服务端接收响应ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);5、关闭套接字close服务端1、创建套接字将进程与网卡进行关联int socket(int domain, int type, int protocol);2、为套接字绑定地址信息2.1、发送端绑定的地址就是源端地址2.2、接收端告诉PC哪些数据交给我int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);3、开始获取网卡上的接收到的指定数据-本质从socket接收缓冲区取出数据ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);4、向客户发送响应数据-本质向socket发送缓冲区放入数据ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);5、关闭套接字释放资源编写简单的程序代码close3.4、UDP的编程注意事项①UDP不保证数据安全有序到达对端因此若需要的话则需要程序员在应用层进行安全管理包序管理②UDP报文有最大长度限制因此发送数据的时候若数据过大则需要程序员在应用层进行分包将大数据分割成多个小段进行发送。③UDP无连接因此支持广播传输一对多的通信通过一次sendto发送数据可以将数据发送给当前局域网网络中的所有主机。四、TCP通信程序的编写流程4.1、协议特性面向连接、可靠传输、面向字节流面向连接通信双方需要维护对方的状态以便于保证数据传输是有效的有意义的可靠传输确保数据能够安全有序的到达对端面向字节流以字节为单位进行传输不限制传输大小先发先到连接管理三次 握手建立连接四次挥手断开连接4.2、TCP协议格式协议格式16位源端端口对端端口---描述通信两段进程序号确认序号---32位序号实现有序传输的核心字段描述数据的序号------32位确认序号实现有序传输的核心字段4位头部长度6位保留 6位标志位URG,ACK,PSH,RST,SYN,FIN16 位窗口大小用于 TCP 的滑动窗口机制实现流量控制避免发送方发送数据过快导致丢包16位校验和二进制反码求和算法实现校验接收到的数据与发送数据是否一致的紧急指针存储一个偏移量指向紧急数据的末尾0~40字节的选项数据----通常用于连接建立时的一些协商数据数据6位标志位标志名称含义URG紧急指针有效位用于表示后边的紧急指针数据是否有效ACK确认应答标志位标识当前报文是一个确认应答报文用于连接建立PSH立即传输标志位TCP 默认有延迟发送机制该标志位用于标识立即发送不要延迟RST重置连接标志位通知对方若要通信则重新建立连接SYN建立连接标志位标识当前报文是一个连接建立请求报文FIN连接断开标志位标识当前报文是一个连接断开报文用于通知对方我不在给你发送数据了4.3、TCP通信程序的编写流程客户端1.创建套接字int socket(int domain, int type, int protocol);2.为套接字绑定地址 根据需要选择是否主动绑定3.连接服务器connect(fd,srvaddr,addlen)4.与服务端进行通信recv/send5.关闭套接字close服务端1.创建套接字让进程与网卡关联int socket(int domain, int type, int protocol);2.为套接字绑定地址信息int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);3.开始监听listen(sockfd,int backlog)告诉操作系统我可以开始接收客户端的连接请求backlog限制同一时间并发请求数4.获取新连接fdacceptstfd,*addr,*addlen将就绪的新连接从内核的就绪连接的队列中取出并返回连接socket对应的描述符通过套接字描述符5.通过accept获取的新连接与客户端进行通信recv/send recv(fd,buf,len,flag)因为新建的每个通信套接字中都有完整的五元组可以通过这个socket知道与哪个客户端通信6.关闭套接字close在TCP通信中套接字是区分了两种监听套接字是最早的服务端通过socket创建的套接字只用于处理新连接通信套接字是客户端连接到服务端成功后创建的新连接 用于与客户端通信4.4、TCP的三次握手和四次挥手4.5、典型题目 4.4.1、三次握手的过程是什么样的客户端向服务端发送SYN请求 服务端回复ACKSYN;客户端回复 ACK4.4.2、握手为什么是三次为什么不是两次或者四次两次 是不够安全的当前的SYN有可能是正常的也有可能是延迟到达的无效报文。四次是没有必要的因为每个报文都要传输报头占据带宽4.4.3、挥手为什么是四次而不是三次FIN包 主要用于表示我不给对方发送数据了并不表示我不再接收数据但是不表示 对方不再给我发送数据因此对方依然可以继续发送数据给我因此从设计上讲两个操作给分开了4.4.4、三次握手中超时时双方是如何处理的①客户端发送SYN后等待超时客户端会重传SYN请求次数限制②服务端发送SYNACK后等待超时客户端不对服务端进行确认会怎么样服务端会给客户端回复一个RST报文然后释放socket4.4.5、TIME_WAIT状态投什么作用①主动关闭方收到了对方的FIN并进行回复后进入的状态②等待两个MSL时间后进入CLOSED状态释放连接MSL报文最大生命周期因为主动关闭方最后一次的ACK有可能会丢失 对方收不到AKC超时就会重传FIN一旦主动关闭方直接进入closed释放连接就有可能有新连接使用了相同的地址收到这个重传的FIN包因此为俩 避免产生这种情况因此主动关闭方等待两个MSL之后再进入closed释放连接为什么是两个MSL因为第一个MSL是保证ACK的最大生命周期第二个MSL是重传的FIN的最大生命周期。4.4.6、一台主机上出现大量的TIME_WAIT连接是什么原因怎么解决①time_wait是主动关闭方才会出现的状态②主机上出现了大量的time_wait意味着主机上频繁的且大量的在进行主动连接关闭操作这种情况常见于主机运行了爬虫程序。解决方案两种第一种使用setsockopt接口进行套接字选项设置开启地址重用复用处于time_out状态连接地址第二种进行系统配置设置调整MSL等待时间4.4.7、一台主机上出现了大量的close_wait状态连接这是怎么回事被动关闭方收到FIN并进行ACK恢复后进入的状态等待上层关闭连接若产生大量close_wait有可能是代码漏掉了close关闭连接操作连接断开了但是没有close。4.6、连接断开在程序中的表现recv取完所有数据后返回0则不再阻塞send触发异常SIG_PIPE让程序直接退出避免退出忽略或自定义SIGPIPE信号的处理方式TCP的连接保活机制服务端与客户端若长时间没有数据往来则会每隔一段时间给客户发送一个保活探测数据包要求客户进行确认恢复若连续多次都没有收到回复则认为连接断开释放资源。4.7、可靠传输可靠传输保证数据安全有序的到达对端。核心发送方和接收方如何发现出现了丢包丢包后该如何处理如何尽量避免丢包以下两个核心机制①确认应答机制发送针对发送的每一个字节数据都要求接收方收到之后进行确认恢复若发送数据后长时间没有收到回复则认为丢包②超时重传机制发送方等待超时发现丢包后就会对原来的数据进行重传。避免没必要的丢包①滑动窗口机制通过协议中的窗口大小字段避免发送方发送数据过块导致接收方接收缓冲区溢出导致丢包。接收窗口的滑动窗口大小前沿-后沿取决于对方相应数据中的窗口大小字段。后沿的移动当收到了后沿序号的确认应答前沿的移动响应的窗口大小---后沿发送窗口的大小一定是等于响应数据中的窗口大小字段。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →