网络中名称解释
套接字:在协议栈内部有一块用于存放控制信息的内存空间,这里记录了用于控制通信操作的控制信息,例如通信对象的 IP 地址、端口号、通信操作的进行状态等。我们可以说这些控制信息就是套接字的实体,或者说存放控制信息的内存空间就是套接字的实体。
描述符:应用程序识别套接字的一种机制(计算机内部)。
端口号:让通信的另一方(计算机)能够识别出套接字的一种机制。
PID号:操作系统为了标识程序而分配的编号。
网络中数据的传输过程(TCP和IP协议)
- 连接
主要功能:建立客服端和服务端之间能进行信息交互的通道。
具体过程:
首先应用程序调用socket申请套接字。
这时协议栈(不同操作系统有自己不同的协议栈)会分配空间,同时初始化空间,这个空间被称为套接字,协议栈并返回一个描述符给应用程序,描述符是为了区分协议栈中不同的套接字的,类似于套接字的门牌号。因为套接字中有通讯双方的信息和通讯状态,所以应用程序发送消息时只需要告诉协议栈描述符即可完成通讯。
其次应用程序调用connect。
它提供了服务器的IP地址和端口号,与服务器进行连接;连接包括以下几个步骤:
A 客服端创建TCP控制信息头部,并将SYN = 1,设置适当的序号和窗口大小(seq),发送给服务器,服务器接收解析后,将套接字状态变为正在连接;
SYN = 1 (连接标志)seq = x (客服端发送数据开始初始化的序号)
B 同样服务器也创建TCP控制信息,SYN = 1(如果服务器繁忙则RST= 1),ACK =1(告知已接受数据)通过网络发送给客服端;
SYN = 1 seq = y(客服端发送数据开始初始化的序号)ACK = 1 (告知已接受数据)ack = x+1 (告知对方x+1序号前的数据已经接受)
注:ACK和SYN是TCP头部控制位,ACK表示表示接收数据序号字段有效,一般表示数据已被接收方收到而不是表示ACK 号。
C 如果客服端接收到数据包将连接状态改变为连接完成,并且将服务器的IP地址与端口号写入套接字中。因接收到的SCK = 1所以客服端还需要在发送一次信息给服务器告诉服务器刚才的响应包已经收到。当这个服务器收到这个返回包之后,连接操作才算全部完成。
ACK = 1 seq = x+1(发送数据的序号) ack = y+1
过程如图(三次握手)
Seq表示本机初始随机序号,ack表示希望下一次接收到对方发过来的序号
三次握手的原因:三次握手可以防止已经失效的连接请求报文突然又传输到服务器端导致的服务器资源浪费。例如,客户端先发送了一个SYN,但是由于网络阻塞,该SYN数据包在某个节点长期滞留。然后客户端又重传SYN数据包并正确建立TCP连接,然后传输完数据后关闭该连接。该连接释放后失效的SYN数据包才到达服务器端。在二次握手的前提下,服务器端会认为这是客户端发起的又一次请求,然后发送SYN ,并且在服务器端创建socket套接字,一直等待客户端发送数据。但是由于客户端并没有发起新的请求,所以会丢弃服务端的SYN 。此时服务器会一直等待客户端发送数据从而造成资源浪费。
2.数据传输
数据传输是从应用程序调用write开始,应用程序会把数据交付给协议栈,协议栈不会管数据是什么,对协议栈而言都是二进制数字。协议栈不会马上发送数据而是把数据放到一个缓冲区中,再根据情况发送。影响因素主要有两个:数据长度、等待时间。
每个网络包都有一定的长度:
MTU:一个网络包的最大长度,以太网中一般为 1500 字节。
MSS:除去头部之后,一个网络包所能容纳的 TCP 数据的最大长度。
通过“序号”和“ACK 号”可以确认接收方是否收到了网络包。这也是为什么TCP是可靠传输的原因。
3.断开
协议栈在设计上允许任何一方先发起断开过程。
客户端先发起断开,则断开的操作顺序如下。
1.客户端发送 FIN
FIN = 1(表示断开连接)seq = u(发送数据的序号)
2.服务器返回 ACK 号
ACK = 1(告知已接收数据)ack = u+1(u+1前数据已接收)seq = v(服务器发送数据的序号)
3.服务器发送 FIN
FIN = 1 seq = w(w>v发送数据的序号) ACK = 1(告知已接收数据) ack = u+1(u+1前数据已接收)
4.客户端返回 ACK 号
ACK = 1 ack = w+1(w+1前数据已经接收)
删除套接字
和服务器的通信结束之后,用来通信的套接字也就不会再使用了,这时我们就可以删除这个套接字了。不过,套接字并不会立即被删除,而是会等待一段时间之后再被删除。
例如:客户端先发起断开,则断开的操作顺序如下。
(1)客户端发送 FIN
(2)服务器返回 ACK 号
(3)服务器发送 FIN
(4)客户端返回 ACK 号
如果最后客户端返回的 ACK 号丢失了,结果会如何呢?这时,服务器没有接收到 ACK 号,可能会重发一次 FIN。如果这时客户端的套接字已经删除了,会发生什么事呢?套接字被删除,那么套接字中保存的控制信息也就跟着消失了,套接字对应的端口号就会被释放出来。这时,如果别的应用程序要创建套接字,新套接字碰巧又被分配了同一个端口号B ,而服务器重发的 FIN 正好到达,会怎么样呢?协议中对于这个等待时间没有明确的规定,一般来说会等待几分钟之后再删除套接字。
四次挥手的原因:由于连接的关闭控制权在应用层,所以被动关闭的一方在接收到FIN包时,TCP协议栈会直接发送一个ACK确认包,优先关闭一端的通信。然后通知应用层,由应用层决定什么时候发送FIN包。应用层可以使用系统调用函数read==0来判断对端是否关闭连接。