🌈前言🌈
欢迎收看本期【网络世界】,本期内容讲解TCP/IP协议栈中的传输层协议,即UDP协议和TCP协议。包含了他们的协议格式,特点等。介绍他们的应用场景,最后对比TCP与UDP协议。此外,还将介绍套接字是如何工作的。
📁 传输层
传输层是负责数据传输和数据控制的一层,提供主机应用程序之间端到端的连通性。传输层位于中间层,具有承上启下的作用。
功能:
1. 复用和分用:由于一个主机同时运行多个进程,传输层具有复用和分用功能,能够在单个网络连接上创建多个逻辑连接。
2. 数据传输服务:TCP提供面向连接的可靠服务,包括流量控制,差错控制和序列控制,确保报文无差错,无丢失,无重复,无乱序地传输。UDP提供面向无连接的数据传输。
3. 连接管理:负责传输连接的建立,维护和释放,确保数据传输的可靠性和完整性。
📁 端口号
端口号(Port)标识一个主机上通信的不同应用程序,即不同进程。一个进程可以绑定多个端口号,一个端口号只能绑定一个进程
在TCP/IP协议中,通过"源 IP", "源端口号", "目的 IP", "目的端口号", "协议号" 这样一个 五元组来标识一个通信(可以通过 netstat -n 查看);
📂 端口号范围划分
0 - 1023:知名端口号,HTTP,FTP,SSH等这些广为使用的应用层协议,它们的端口号都是固定的。
1024 - 65535:操作系统动态分配的端口号,客户端程序的端口号,就是有操作系统从这个范围分配的。
📂 知名端口号
有些服务器是非常常用的,为了使用方便,人们约定一些常用的服务器,都是使用一下这些固定的端口号:
• ssh 服务器, 使用 22 端口
• ftp 服务器, 使用 21 端口
• telnet 服务器, 使用 23 端口
• http 服务器, 使用 80 端口
• https 服务器, 使用 443
自己写的程序使用端口号时,要避免这些知名端口号。
使用以下命令可以查看知名端口号:
cat /etc/services
📁 报文
通信双方,一定存在很多报文,有的在接收,有的在处理,有的在发送。因此,需要对报文进行管理。
报文通过双向链表组织起来,用一个结构体字段描述,其中结构体字段内包含两个指针,指向一段空间的中间,当要添加报头时,head指针向前移动,进行强转报文的类型,然后添加报头数据。添加数据data指针则向后移动。
📁 UDP协议
📂 协议格式
我们通过学习UDP协议格式,来对UDP协议做一个整体认识,学习UDP的工作原理。
UDP协议就是将上层传下来的数据添加8字节的UDP报头。
源端口和目的端口如字面意思。16位UDP长度,表示UDP报文的总长度最大为2^16。16位UDP校验和在数据传输过程中进行数据完整性检查和差错检测。
16位UDP长度就规定了,UDP数据报在理论上最多64KB(包含UDP报头和数据)。然而64K在当前互联网下是一个很小的数字。因此,如果我们想要传输的数据超过64K,就需要手动的在应用层进行分包,多次发送,并在接收端手动拼接。
16位校验和可以用于数据完整性检查,检测UDP数据报在传输过程中是否发生了损坏和改变。也能进行差错检测,能够检测到传输过程中发生的任何单个比特的错误。
数据完整性检查: UDP校验和用于检测UDP数据报在传输过程中是否发生了损坏或改变。发送端在发送UDP数据报之前会计算校验和,并将其添加到UDP头部中。接收端收到数据后也会计算校验和,然后将其与接收到的UDP头部中的校验和进行比较。如果两者不一致,则表明数据在传输过程中发生了错误或损坏,接收端可以丢弃这个数据包或请求重新发送。
差错检测: UDP校验和能够检测到在传输过程中发生的任何单个比特的错误。它通过对UDP数据报中的所有字节进行求和,并进行一定的逻辑运算(取反或补码)来生成一个检验和。接收端也会对接收到的数据进行相同的操作,并将结果与发送端发送的校验和进行比较。如果校验和不匹配,则说明数据包可能已经损坏,需要进行重传或其他错误处理机制。
总结来说,UDP校验和主要用于增强UDP协议在不可靠的IP网络上的数据完整性和可靠性,尽管UDP本身不提供可靠性保证。
当然不可靠是什么,在这里我们看一下介绍即可,只有学习了TCP的可靠连接是什么,才能真正理解UDP不可靠的含义。
📂 特点
● 无连接 : 不需要建立连接,直到对端的IP和端口号,就能给对方发送数据。
● 不可靠 :没有确认机制,重传机制。如果因为网络故障等问题导致数据丢失,UDP协议层不会给应用层返回任何错误信息。
● 面向数据报 :不能灵活的控制读写数据的次数和数量。应用层给UDP多长的保温桶,UDP原样转发,不会拆分,也不会合并。
📂 缓冲区
• UDP 没有真正意义上的 发送缓冲区. 调用 sendto 会直接交给内核, 由内核将数据传给网络层协议进行后续的传输动作。
• UDP 具有接收缓冲区. 但是这个接收缓冲区不能保证收到的 UDP 报的顺序和发送 UDP 报的顺序一致; 如果缓冲区满了, 再到达的UDP 数据就会被丢弃。
UDP 的 socket 能同时读写, 这个概念叫做全双工。
全双工(Full Duplex)是一种通信方式,它允许数据在通信链路的两个方向上同时传输,即发送和接收可以同时进行,无需等待对方完成。这种通信方式大大提高了数据传输的效率,因为它消除了等待时间,使得双方可以几乎同时发送和接收信息。
在全双工通信中,每个设备(如计算机、路由器、交换机等)都有独立的发送和接收通道,这些通道可以同时工作,互不干扰。
📂 使用UDP协议的上层协议
• NFS: 网络文件系统
• TFTP: 简单文件传输协议
• DHCP: 动态主机配置协议
• BOOTP: 启动协议(用于无盘设备启动)
• DNS: 域名解析协议
📁 TCP协议
TCP 全称为 "传输控制协议(Transmission Control Protocol"). 人如其名, 要对数据的传 输进行一个详细的控制。
📂 协议格式
与UDP学习机制一样,我们先通过TCP协议的格式来了解什么是TCP,TCP工作流程,最后介绍TCP协议的特定以及通过哪些策略来确保数据传输的可靠性。
学习任何协议之前,都需要有两个问题解决:1. 怎么封装/解封装;2. 怎么分用
1. 封装/解封装:这个问题解决的就是我们知道哪些是报头,哪些是数据,因此主机收到的都是一些二进制字符串,想要识别出数据,就要有一些标识符,或者提示字段。
在UDP格式中,有16位标识字段告诉我们数据报的大小,其中报头字段的大小是固定的8字节,两个数字相减就是我们要的数据。
在TCP协议中,通过4位的首部长度来明确报头+选项的长度,剩下的就是数据。基本单位是 4B,意味着 [0 , 15] * 4B 变成[ 0 , 60]字节,其中20字节的报头长度,40字节的选项。如果首部长度为0101,则无选项;大于等于0101的那些字节数就表示选项字节数。
2. 分用:TCP和UDP协议都是通过16位端口号来确定将数据交给哪个进程。
这样,我们就学了TCP报头中的3个字段,剩下的字段,我们在学习TCP各种策略的时候详细学习。
不同TCP报文有不同作用,因此需要一个标记位,来表明是用来干什么的:
ACK:确认标志,确认信号是否有效。即对发信息的主机给出响应,表示成功收到数据
URG:紧急指针是否有效
PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走
RST:对方要求重新建立连接;把携带RST标识的称为复位报文段
SYN:请求建立连接;把携带SYN标识的称为同步报文段
FIN:通知对象,本端要关闭了,把携带FIN标识的称为结束报文段
📂 确认应答(ACK)机制
我们平时对一个人说话,怎么直到对方收没收到呢,最简单的一种方法不就是对方给我回消息了,不就证明对方收到了吗。
总有最新的一条信息,没有应答,因此不对应答做出应答。
可靠性:知道报文是否丢失,是否成功送达。收到应答,就认为数据成功收到;没有收到应答,不管是否成功送达,都认为数据丢失。
ACK:确认标志,确认信号是否有效。即对发信息的主机给出响应,表示成功收到数据
但是这样接受一个发送一个的效率太低了,因此,TCP协议都是多对多的接受和发送。
一般采用多对多模式,即一次发送多个报文,但是如果有报文丢失,没有应答,怎么知道是哪个报文丢失了呢。因此就需要唯一标识报文字段,即序号。
序号(Sequence Number)
序号的主要作用是用于将失序的数据重新排列,确保数据传输的顺序性。在TCP/IP协议中,TCP会对字节流中的每个字节进行隐式编号,而TCP报文段的序号被设置为其数据部分的第一个字节的编号。序号是一个32位的无符号数,其取值范围是0到2^32-1,这足以对大量数据进行编号,保证数据传输的顺序性。
确认序号(Acknowledgment Number)
确认序号是接收方向发送方发送的确认消息中包含的一个字段,用于告知发送方接收方已经成功接收到的数据的序号。
TCP将每个字节的数据进行了编号,即为序列号。接收端发送的报头都带有对应的确认序列号,意思是告诉发送者,我已经收到哪些数据了;下一次你从哪里开始。
确认序号 = 序号 + 1,表示 [0 ,序号] 范围内数据已经收到,下次你从序号+1的位置开始发送数据吧。
TCP发送方在发送每个TCP报文段时,会根据发送的数据字节数递增序号。 TCP协议要求序号必须对应于报文段中首字节的数据位置。例如,如果报文段包含100字节的数据,则下一个报文段的序号将比前一个报文段的序号增加100,即第一个报文序号是0,第二个发送报文的序号是101。
接收方使用确认序号(Acknowledgment Number)来指示下一个期望接收的序号。确认序号表明已经接收到的字节,使发送方可以了解哪些数据已经被接收,哪些数据需要重传。
序号作用:
1. ACK机制:发送序号,收到确认序号,来表明数据已收到,下次从哪发数据。
2. 去重:当报文丢失时,即确认序号没有收到,TCP就知道报文丢失,就会重传。
3. 按序到达,这就是TCP的可靠性:接收端TCP将接收到的报文按照序号排序号,就能得到完整的数据。
📂 超时重传
我收到ACK,就是对方收到数据;我没有收到ACK,就默认对方没有收到数据。
在特定的时间间隔内内,我没收到ACK,就认为对方没有收到数据,进行超时重发。
但是如果ACK丢了,服务器收到了数据,重发就会导致重复数据,因此,TCP协议就需要识别重复的包并丢弃,这里就利用序列号,从而做到去重的效果。
TCP 为了保证无论在任何环境下都能比较高性能的通信, 因此会动态计算这个最大超时时间。
📂 连接管理
TCP协议在读写数据前需要进行连接建立,在结束通信时需要关闭。这个过程叫做连接管理,即3次握手,4次挥手。
3次握手
1. 客户端发情建立连接的请求,即发送一个报头(SYN置为1)。
2. 服务器返回一个应答,即也发送一个报头(SYN置为1,ACK置为1)。这里使用了捎带应答技术,既表示了对客户端SYN的应答ACK,也表示给客户端发送一个建立连接的请求SYN。
3. 客户端收到服务器的ACK,认为连接建立,此外还收到服务器的SYN请求,应答ACK。客户端认为连接已经建立好了。
4. 服务器如果收到客户端的ACK,认为连接也建立好了。如果没有收到,就认为连接建立失败就会给客户端发送一个报头(RST置为1),要求释放异常连接,重新建立连接。
RST:对方要求重新建立连接;把携带RST标识的称为复位报文段
SYN:请求建立连接;把携带SYN标识的称为同步报文段
4次挥手
1. 客户端想要结束通信,关闭连接时,想服务器发送请求报头(FIN置为1)。
2. 服务器返回一个应答,即也发送一个报头(ACK置为1),因为服务器可能还在处理客户端数据,给客户端发送数据,因此服务器不能立马给客户端发送一个FIN。
3. 当服务器处理完客户端数据,在合适时机就会给客户端也发送一个FIN请求,客户端会给服务器返回一个ACK,服务器等待ACK的到了,收到ACK表示连接结束。
1. 为什么是3次握手,不是4次?
理解连接是相互的,不仅你要连接我,我还要连接你。因此,客户端给服务器发送SYN表示建立连接,服务器也要给客户端发送SYN请求建立连接。但是服务器的SYN和ACK使用捎带应答技术,可以将这两个字段放在一个应答中,因此是3次握手。
2. 为什么是4次挥手,不是3次?
服务器可能还在处理客户端数据,给客户端发送数据。客户端关闭连接,并不意味着不能接受数据,处在TIME_WAIT期间内,依然可以收到服务器发送来的数据。当服务器处理完数据,向客户端发送FIN,客户端向服务器ACK应答。
3. 3次握手的好处:
验证网络连通性。客户端能发消息,也能收消息。服务器也能收消息,发消息。建立双方通信的共识意愿。
4. 4次挥手的好处:
最小的通信成本,建立断开连接的共识。即双方都不和对方通信,且知道对方也不和我通信。
状态码
我们可以看到上图中两侧有不同的状态码,分别表示什么含义呢?
服务器:
【CLOSED -> LISTEN】:服务器调用socket,bind,listen进入LISTEN状态,等待客户端连接。
【LISTEN -> SYN_RCVD】:一旦监听到请求连接,就将该连接放入内核等待队列中,并向客户端发送SUN确认报文。
【SYN_RCVD -> ESTABLISHED】:服务器一旦受到客户单的确认报文,进入ESTABLISHED状态。 如果服务器没有收到ACK就向客户端发送报文(RST)要求重新建立连接,释放原来异常的连接
【ESTABLISHED -> CLOSE_WAIT】:服务器收到客户端主动关闭连接的请求,服务器会受到结束报文段,服务器返回确认报文段CLOSE_WAIT。
【CLOSED_WAIT -> LAST_ACK】:服务器处理完剩余数据,关闭连接,发送FIN,进入LAST_ACK状态,等待最后一个ACK的到来。
【LAST_ACK -> CLOSED】:服务器收到FIN的ACK,彻底关闭连接。
客户端:
【CLOSED -> SYN_SENT】:客户端调用 connect, 发送同步报文段。
【SYN_SENT -> ESTABLISHED】:connect 调用成功, 则进入 ESTABLISHED 状 态, 开始读写数据。
【ESTABLISHED -> FIN_WAIT_1】:客户端主动调用 close 时, 向服务器发送结 束报文段, 同时进入 FIN_WAIT_1。
【FIN_WAIT_1 -> FIN_WAIT_2】:客户端收到服务器对结束报文段的确认, 则进 入 FIN_WAIT_2, 开始等待服务器的结束报文段。
【FIN_WAIT_2 -> TIME_WAIT】:客户端收到服务器发来的结束报文段, 进入 TIME_WAIT, 并发出 LAST_ACK。
【TIME_WAIT -> CLOSED】:客户端要等待一个 2MSL(Max Segment Life, 报文 最大生存时间)的时间, 才会进入 CLOSED 状态。
TIME_WAIT
主动关闭连接的一方要处于TIME_WAIT的状态,等待两个MSL的时间后才能回到CLOSED状态 。在TIME_WAIT期间内,其他进程不能监听该端口。
MSL(报文最大生存时间)
就是报文在网络中允许存在的时间,如果超过该时间,就会被丢弃。即MSL是指一个TCP报文段在网络中的最大生存时间,它限制了一个报文段在网络中传输的最长时间。一旦超过这个时间,如果报文段仍未到达目的地,它将被丢弃。这个时间通常由操作系统内核定义,并且在不同的操作系统中可能有所不同。
时间是以秒为单位,因此,在被丢失之前,该报文已经被重传了,超时重传是以ms为单位。
因此,MSL可以很好的防止旧的数据包的持续存在;确保网络状态的及时更新;避免浪费资源和网络拥塞
TIME_WAIT保证两个方向上未被接收或迟到的报文段已经消失,确保新连接不会受到上一条连接的影响(否则主动关闭的一方,不管最后一个ACK是否到大,都关闭连接,重新建立新的连接,这样可能导致新的连接收到上一条连接的报文,导致数据错误)。
理论上保证了最后一个报文可靠到达(假设最后一个ACK丢失,那么服务器就会重新发送一个ACK,虽然客户端进程不在了,但是TCP是有OS kernal维护,仍然可以重发ACK)。
CLOSE_WAIT
例如,客户端关闭写端,不发送数据,但是服务器可能还要处理数据,发送给客户端,那么客户端就可以通过读端收到,返回ACK。
📂 滑动窗口
我们一次发送多条数据, 就可以大大的提高性能,但是有一个问题是我怎么知道对端能处理多少数据,如果我一下发送的报文太多了,对端根本不能接受,就会丢弃,那么我收到不ACK,就会一种重传,就导致出现故障。
因此,需要一个字段来告诉发送方,接收方能接收多少数据,别发超了。
窗口大小指的是无需等待确认应答而可以继续发送数据的最大值,即对端缓冲区内剩余空间的大小。上图的窗口大小就是 4000 个字节(四个段)。
发送前四个段的时候, 不需要等待任何 ACK, 直接发送。
收到第一个 ACK 后, 滑动窗口向后移动, 继续发送第五个段的数据; 依次类推。
操作系统内核为了维护这个滑动窗口, 需要开辟发送缓冲区来记录当前还有哪些数据没有应答; 只有确认应答过的数据, 才能从缓冲区删掉。
窗口越大, 则网络的吞吐率就越高。
我们可以将发送缓冲区理解为一个环形队列,窗口左移的过程,做部分已发送,已确认数据就销毁了,下次直接覆盖写了。因此滑动窗口是不需要向右的,只能往左移动。
快重传
快重传(Fast Retransmit)机制是TCP协议中的一种错误恢复机制,它通过更早地检测到数据包的丢失,并立即触发重传来加速数据恢复过程。这种机制减少了数据传输的延迟,提高了网络效率。
快重传机制的工作原理基于接收方发送的重复确认(Duplicate ACK)信息。具体过程如下:
重复ACK:当接收方收到一个乱序的数据包(即不是按序到达的数据包)时,它会针对已正确接收的最高序列号的数据包发送ACK确认。如果后续又有数据包丢失,接收方会继续发送针对同一序列号(即已正确接收的最高序列号)的重复ACK。
三重重复ACK:如果接收方连续三次收到针对同一序列号的重复ACK,则认为该序列号之后的数据包已经丢失,并且后续的数据包正在按序到达。这时,接收方会向发送方发送一个特殊的“三重重复ACK”信号。
快速重传:发送方在收到“三重重复ACK”后,会立即重传丢失的数据包,而不是等待正常的超时时间到期后再进行重传。这样做可以更快地恢复数据传输,减少延迟。
快重传机制和超时重传机制相辅相成。超时重传更类似于兜底的,如果没有触发第3个重复ACK,且超过超时时间范围,那么发送端也会重发,两个机制共同作用。
📂 流量管理
接收端处理数据的速度是有限的,如果发送端发的太快,导致接收端的缓冲区被打满,这时入关还要继续发送,就会造成丢包,从而引起丢包重传等一系列连锁反应。因此,TCP支持根据接收端的处理能力,来决定发送端的发送速度,这个机制就叫做流量控制。
流量控制就是通过滑动窗口来实现的。16位数字最大表示为65535,那么TCP窗口最大就是这个了吗。实际上TCP40B的选项内还包含一个窗口扩大因子M,实际窗口是窗口字段的值左移M位。
窗口
如果服务器接受缓冲区满了,会向客户端发送报头(16位窗口大小为0)。但是客户端不能一直等吧,因此客户端每隔一时间,会发送一个窗口探测包,询问窗口大小。如果不为0,发送请求。
此外,如果服务器刚发送窗口大小为0的报头,上层处理厂数据,缓冲区有空间了,服务器会向客户端发送一个窗口更新通知,告知客户端窗口大小。
📂 拥塞控制
如果网络中积累了大量数据包没有被处理,就会造成网络拥塞问题,即发送的报文都可能不被处理而触发超时重传。拥塞控制,就是TCP协议想要尽可能的将数据传输给对方,但是又要避免给网络造成太大的压力的这种方案。
如果当前网络阻塞,TCP规定不能再发了大量数据了,引入了 慢启动 机制,即先发送少量的报头探测网络状态,再决定按照多大的速度传输。
此处引入一个概念称为拥塞窗口。
发送开始的时候, 定义拥塞窗口大小为 1。
每次收到一个 ACK 应答, 拥塞窗口加 1。
每次发送数据包的时候, 将拥塞窗口和接收端主机反馈的窗口大小做比较, 取较小的值作为实际发送的窗口。
发送端滑动窗口的大小 = Min(拥塞窗口,接收端窗口)最小值。
拥塞窗口的出现,就是为了防止网络拥塞,而主机不断发送数据的情况。
拥塞窗口的增长速度是指数级别的(2^N),但是不能一直增长,引入 慢启动的阈值,当超过阈值,按照线性增长。
拥塞窗口阈值(ssthresh)是一个重要的参数,用于决定拥塞窗口(cwnd)的增长方式。当拥塞窗口的大小小于ssthresh时,拥塞窗口的增长方式是快速的(如指数增长);而当拥塞窗口的大小达到或超过ssthresh时,拥塞窗口的增长方式则变为慢速的(如线性增长)。
- 慢启动与拥塞避免的分界:ssthresh作为慢启动阶段和拥塞避免阶段的分界点。在慢启动阶段,拥塞窗口以指数方式增长,直到达到ssthresh;然后进入拥塞避免阶段,拥塞窗口以线性方式增长。
- 调整发送速率:通过调整ssthresh的值,TCP可以动态地调整其发送速率,以适应网络条件的变化。当网络出现拥塞时,ssthresh会被降低,以减少发送方注入网络的数据量;而当网络状况改善时,ssthresh可能会逐渐增大。
📂 延迟应答
如果接收端接收到报文立即返回ACK,可能返回的窗口大小较小,因此等待一段时间,如果该时间内上层处理了数据,那么就可以发送一个更大的窗口,提高效率
举个例子,外卖员取两份出餐时间间隔很短且在一家店的外卖,第一份出餐,第二份就在3s后出餐,快递员为了效率,会不等这3s吗。
当然也不是一直延迟等待中,也是有数量和时间限制的。
数量限制:每隔N个包就应答一次。
时间限制:超过最大延迟时间就应答一次。
具体的数量和超时时间,不同OS不同,一般N取2,延时时间取200ms。延时时间一定不会超过超时重传的时间。
📂 捎带应答
客户端服务器在应用层是“一发一收”,意味着服务器给客户端发送数据时,也可以捎带着ACK,一起发给用户。
📂 字节流和粘包问题
TCP是面向字节流的协议。
创建一个 TCP 的 socket, 同时在内核中创建一个 发送缓冲区 和一个 接收缓冲区。
1. 调用write将数据拷贝到缓冲区。
2. 如果缓冲区数据太长,会被拆分成多个TCP数据包发送出去。
3. 发送的数据太短,会在缓冲区里等待,等缓冲区差不多了,或者其他合适时机发送出去。
4. 接受数据,数据从网卡驱动程序送到内核的接收缓冲区,接收端调用read将数据拷贝给上层。
粘包问题中,包指的是上层传递下来的数据包;TCP中没有如同UDP一样的报文长度,TCP通过序号将报文传递,按序号存放在缓冲区 ,应用层角度只能看到一串字节数据
如何解决粘包问题?明确报文之间的边界。例如\r\n,http协议就采用\r\n之间明确边界。
📂 异常问题
进程终止:进程终止释放文件描述符,OS仍然可以发送FIN,TCP协议由OS kernal维护,和正常关闭没有区别。
机器重启/关机:和终止进程没有区别。
机器断点/网线断开:接受端有写入操作,发现连接断开,就会进行reset;此外,TCP也内置了保活定时器,会定期询问对方是否还在,如果对方不在,就会把链接释放。
📂 tcpdump抓包
1. 捕获所有网络接口上的TCP报文
2. 捕获指定网络接口上的TCP报文
3. 捕获特定 源或目的IP地址的TCP报文
4. 捕获指定端口的TCP报文
5. 将捕获的数据包保存到文件
6. 从文件中读取数据包进行解析
📁 全连接队列 (套接字工作过程)
我们通过了解TCP中的listen系统调用的第二个参数,来学习套接字的工作过程。
listen的第二个参数backlog的作用
当通信双方建立连接时,服务器会调用accept接收该连接。但当上层没时间Accept时,TCP listen socket也允许建立连接,但是不能超过backlog + 1个(不代表只能处理backlog+1个连接)。因为Accept作用在3次连接建立后。
backlog不能为空,因为上层没时间accept时,用户长时间建立不起连接,就关闭了,增加了服务器的闲置率;也不能太长,尾部连接一直不能处理,关闭连接时,用户体验差,也浪费空间。
连接本质是一个结构体对象,通过accept_queue组织。上层调用accept获取连接结构体。
我们可以简单理解为,三次握手过程中创建和初始化struct sock,这个过程发生在内核空间。
具体来说,在TCP连接的三次握手过程中:
- 当服务器收到客户端发起的SYN请求后,内核会把该连接存储到半连接队列,并向客户端响应SYN+ACK。
- 当服务器收到客户端的ACK确认后,内核会完成三次握手,此时会创建一个新的
struct sock
实例来表示这个已建立的TCP连接,并将其加入到全连接队列中。这个过程发生在内核空间,对用户空间的应用程序是透明的。
struct socket是用户空间对套接字的抽象表示,它在应用程序调用socket()系统调用时被创建,并允许应用程序通过系统调用来操作套接字。
- 应用程序通过调用
socket()
系统调用来创建一个新的套接字。此时,内核会分配一个struct socket
结构体,并返回一个文件描述符(socket fd),即listen套接字,给应用程序。- 应用程序随后可以使用这个套接字来绑定地址和端口(可选,对于服务器套接字是必需的),监听连接(服务器套接字),接受连接(服务器套接字),或者连接到远程服务器(客户端套接字)。
struct tcp_sock可以理解为struct inet_sock的C语言的子类,从而实现C语言版的多态。
📁 TCP与UDP对比
TCP可靠性:校验和,序列号,确认应答,超时重传,连接管理,流量控制,拥塞控制。
TCP提高性能:携带应答,延迟应答,滑动窗口,快重传。
TCP适用于可靠传输,应用于文件传输,重要状态更新等;UDP适用于高数传输和实时性要求较高的通信领域和广播领域。
如何实现UDP可靠传输?可以通过序列号,确认应答,超时重传等策略。
📁 总结
以上,就是本期【网络世界】的内容了,包含了传输层TCP和UDP协议的具体细节,对比了TCP和UDP,介绍了套接字创建到工作流程。
如果感觉本期内容对你有帮助,欢迎点赞,关注,收藏Thanks♪(・ω・)ノ