tcp与udp概念与区别

TCP和UDP是两种主要的传输层协议,TCP提供面向连接、可靠的数据传输,适合文件传输、邮件发送等需要稳定性的场景;UDP则简单快速,适合实时应用如视频通话、直播。TCP通过三次握手建立连接,四次挥手断开连接,确保数据的正确传输,而UDP不保证数据的可靠性,但具有更低的延迟。两者在流量控制、拥塞控制、首部开销等方面有显著区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

tcp与udp:
tcp:传输控制协议,是一种面向连接、可靠的、基于字节留的传输层协议。

udp:用户数据报协议。
ip:网络之间的互联协议。

tcp:
1.是面向连接的,有三次握手和四次挥手。
2.面向字节流的,tcp把数据看成一连串无结构的字节流。
3.是可靠的服务,通过tcp传数据,无差错、不重复、不丢失、顺序到达,包是有序号的,保证数据的正确性,不丢包。报文头里的序号使tcp数据顺序到达。报文头里的确认序号保证不丢包,有累计确认和超时重传机制,有流量控制及拥塞控制的机制。
4、是点对点的连接。
5、首部开销需要20字节。
6、tcp逻辑通信是全双工的可靠信道。
7、适用于传输数据稳定可靠,适用于网络通信质量要求较高的场景,需要准确无误的传给对方,比如传输文件、发的邮件、游览网页等。

udp还有一个非常重要的应用场景,就是隧道网络(比如我们常用的VPN,以及在SDN中用到的VXLAN。

udp:(传输稳定性上要弱于tcp)
1、发送数据前不需要建立连接。
2、面向报文的,没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如ip电话、实时视频会议等)
3、尽最大努力交付,不保证可靠交付,数据发送出去就不管了,可能丢包。
4、支持一对一,一对多,多对一和多对多的交互通信。
5、首部开销小,只有8字节(除了源和目标端口,只有包长度和校验和),性能损耗小,内存资源占用也远远小于tcp。
6、是不可靠信道。
7、速度快,可能会丢包,所以适用于对实时性要求较高、但是对少量丢包并没有太大要求的场景,比如域名查询、语音通话、视频直播等。

udp包头:
除了端口号,基本没有了(只有长度、校验和)

typedef struct _UDP_HEADER 
{
 unsigned short m_usSourPort;       // 源端口号16bit
 unsigned short m_usDestPort;       // 目的端口号16bit
 unsigned short m_usLength;        // 数据包长度16bit
 unsigned short m_usCheckSum;      // 校验和16bit
}__

udp应用场景:
需要资源少,对丢包不敏感不需要一对一建立连接,而是可以广播的形式。需要处理速度快,即使网络拥塞也不退缩。如:直播、实时游戏、物联网。

tcp的包头:
1、源端口和目标端口是不可少的,是占2个字节的16位数字。
2、接下来是包的序号。主要是为了解决乱序问题。不编好号怎么知道哪个先来,哪个后到。序号是 32bit 的无符号数,占4个字节。
3、确认序号。发出去的包应该有确认,这样能知道对方是否收到,如果没收到就应该重新发送,这个解决的是不丢包的问题,也是4个字节
4、Offset:报头长度,4位,给出报头中 32bit 字的数目。需要这个值是因为任选字段的长度是可变的。这个字段占 4bit , 即TCP 最多有 60(15*4) 字节的首部
5、Resrvd:保留区域,6位,保留给将来使用,目前必须置为 0。
6、状态位:占6位,SYN 是发起一个链接,ACK 是回复,RST 是重新连接,FIN 是结束连接。因为 TCP 是面向连接的,因此需要双方维护连接的状态,这些状态位的包会引起双方的状态变更

**URG**:为 1 表示紧急指针有效,为 0 则忽略紧急指针值

**ACK**:为 1 表示确认号有效,为 0 表示报文中不包含确认信息,忽略确认号字段

**PSH**:为 1 表示是带有 PUSH 标志的数据,指示接收方应该尽快将这个报文段交给应用层而不用等待缓冲区装满

**RST**:用于复位由于主机崩溃或其他原因而出现错误的连接。它还可以用于拒绝非法的报文段和拒绝连接请求。一般情况下,如果收到一个 RST 为 1 的报文,那么一定发生了某些问题

**SYN**:同步序号,为 1 表示连接请求,用于建立连接和使顺序号同步( synchronize )

**FIN**:用于释放连接,为 1 表示发送方已经没有数据发送了,即关闭本方数据流

7、窗口大小,TCP 要做流量控制,需要通信双方各声明一个窗口,标识自己当前的处理能力。其占2个字节,表示从确认号开始,本报文的源方可以接收的字节数,即源方接收窗口大小。窗口大小是一个 16bit 字段,因而窗口大小最大为 65535(2^16 - 1)。

8、Checksum:校验和,2个字节,对整个的 TCP 报文段**(包括 TCP 头部和 TCP 数据)**,以 16 位字进行计算所得。这是一个强制性的字段,要求由发送端计算和存储,并由接收端进行验证。
9、Urgent Pointer:紧急指针,2个字节,是一个正的偏移量,和顺序号字段中的值相加表示紧急数据最后一个字节的序号。 TCP 的紧急方式是发送端向另一端发送紧急数据的一种方式。 只有当URG 标志置 1 时紧急指针才有效。
10、Option and Pad:选项和填充,n*4字节,常见的可选字段是最长报文大小 MSS(Maximum Segment Size) 。每个连接方通常都在通信的第一个报文段(为建立连接而设置 SYN 标志的那个段)中指明这个选项,它指明本端所能接收的最大长度的报文段。选项长度不一定是 32 位字的整数倍,所以要加填充位,使得报头长度成为整字数。
11、Data:数据,不定长度,为上层协议封装好的数据

最大报文段长度MSS(Maximum Segment Size):

指明自己期望对方发送TCP报文段时那个数据字段的长度。
比如:1460字节。数据字段的长度加上TCP首部的长度才等于整个TCP报文段的长度。
MSS不宜设的太大也不宜设的太小。
若选择太小,极端情况下,TCP报文段只含有1字节数据,在IP层传输的数据报的开销至少有40字节(包括TCP报文段的首部和IP数据报的首部)。
这样,网络的利用率就不会超过1/41。若TCP报文段非常长,那么在IP层传输时就有可能要分解成多个短数据报片。
在终点要把收到的各个短数据报片装配成原来的TCP报文段。当传输出错时还要进行重传,这些也都会使开销增大。
因此MSS应尽可能大,只要在IP层传输时不需要再分片就行。在连接建立过程中,双方都把自己能够支持的MSS写入这一字段。
MSS只出现在SYN报文中。即:MSS出现在SYN=1的报文段中
MTU和MSS值的关系:MTU=MSS+IP Header+TCPHeader
通信双方最终的MSS值=较小MTU-IP Header-TCP Header

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

typedef struct _TCP_HEADER 
{
 short m_sSourPort;              // 源端口号16bit
 short m_sDestPort;              // 目的端口号16bit
 unsigned int m_uiSequNum;         // 序列号32bit
 unsigned int m_uiAcknowledgeNum;  // 确认号32bit
 short m_sHeaderLenAndFlag;        // 前4位:TCP头长度;中6位:保留;后6位:标志位
 short m_sWindowSize;            // 窗口大小16bit
 short m_sCheckSum;              // 检验和16bit
 short m_surgentPointer;           // 紧急数据偏移量16bit
}__attribute__((packed))TCP_HEADER, *PTCP_HEADER;

三次握手:(创建连接的过程)
1:客户端主动发起SYN的连接请求报文,之后处于SYN-SENT的状态。(询问下,能否与你建立连接)
2:服务端收到发起的连接后,返回SYN,并且ACK(确认)客户端的SYN,之后处于syn-rcvd状态。(返回syn+ack包)
3:客户端收到第二步的消息后,将syn-sent状态改为ESTABLISHED(已连接),向服务端回复ACK消息,client向server的通道建立成功。服务端收到ACK消息后,状态改为ESTABLISHED(已连接)状态,此时server发向client的通道连接建立成功。

为什么要三次握手:
如果网络不顺畅,客户方第一次发送的连接请求没有及时到达服务端的话,会再次发生连接请求,建立连接后,第一次滞留的请求包又送达到服务端,而这次服务端会误认为是第二次发的新连接请求,这会造成服务端认为是两个链接,客户端认为是一个链接的错误。

三次握手本质上来说,为了解决网络信道不可靠问题,即:为了在不可靠的信道上建立可靠的连接。

一包数据可能拆成多包发送,如何解决丢包问题,这些包到达顺序不同,如何解决乱序问题:
1、tcp为每个连接建立发送缓冲区,从建立连接后的第一个字节序列号为0开始,后面每个字节加一。
2、发送数据时,从发送缓冲区取一部分数据,组成发送报文,tcp协议头中会附带序列号好长度(发送报文=序列号+长度+数据内容)
3、接收端收到报文后要回复确认,确认报文中的ACK=接收序列号加长度(要发送的下一包的起始序列号),这样一问一答的方式,使发送端能够确认发送的数据已经被对方收到。
4、发送端也可以一次性发送连续的多包数
据,接收端只需要回复一次ACK就行了,这样发送端可以把待发送的数据分割成一系列的碎片,发送到对端,对端根据序列号跟长度,在接收后构建完整的数据,假设其中丢失某些数据包,接收端可以要求发送端重传(比如丢失了100到199之间数据,接收端向发送端发送ack=100的报文,发送端收到后会重传这一包的数据,接收端收到后会进行补齐),以上过程不区分客服端和服务端,tcp连接是全双工的。

四次挥手:(客户端、服务端都可以发起)
1:假设client发起中断请求,client发送FIN报文。自己进入终止等待1状态(FIN-WAIT-1)。
2:server收到FIN报文后,回复ACK,告诉客户端:请求收到了,但我还没准备好,请继续等我的消息,这时客户端进入FIN_WAIT-2状态,服务端进入close-wait状态,此时服务端还可以再发送数据,客户端还可以再接收数据。
3:当server数据发送完成后,向client发送FIN报文,告诉其:我这边数据发送完了,准备好关闭连接了,服务端进入last-Ack状态。
4:client收到fin后,知道可以关闭连接了,但他不相信网络,怕server不知道要关闭,所以要发生ACK后,进入超时等待time_wait状态,经过超时时间后关闭连接。服务端收到ACK后,立即断开连接,状态为Closed。(client等待2MSL后没有收到回复,证明server已经正常关闭,那它也可以关闭连接了,状态改为closed,这样tcp连接就关闭了)。

为什么客户端要等待超时时间:
这是为了保证对方收到Ack包,假设客户端发送完最后一包Ack包就立即释放连接,一旦Ack包在网络中丢失,服务费一直停留在最后确认状态,如果客户端发送完最后一个Ack包后,等待一段时间,这时如果服务端没有收到Ack包,会重发fin包,客户端会相应这个FIN包,重发Ack包并刷新超时时间。
这个机制跟三次握手一样,也是为了保证在不可靠的网络链路中,进行可靠的连接断开。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

开心码农1号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值