UNIX网络编程·卷一之第二章

UDP用户数据报协议

UDP不保证UDP数据报会到达其最终目的地,不保证各个数据报的先后顺序跨越网络后保持不变,也不保证每个数据报只到达一次。(可与TCP进行对比)

TCP传输控制协议

TCP提供客户与服务器之间的连接,并提供了可靠性。当TCP向另一端发送数据时,他要求对端返回一个确认,如果没有收到确认,TCP就自动重传数据并等待更长时间。在数次重传失败(需注意)后,TCP才放弃。
注意:TCP并不保证数据一定会被对方端点接收,它提供的是数据的可靠递送或故障的可靠通知。

RTT:round-trip time 客户端和服务器之间的往返时间

TCP通过给其中每个字节关系一个序列号对所发送的数据进行排序。如果这些分节非顺序到达,接收端TCP将先根据它们的序列号重新排序,再把结果数据传递给接收应用。如果接收端TCP接收到来自对端的重复数据,它可以根据序列号判定数据是重复的,从而丢弃重复数据。(UDP本身不提供确认、序列号、RTT估算、超时和重传等机制。)

TCP提供流量控制。TCP总是告知对端在任何时刻它一次能够从对端接收多少字节的数据,这称为通告窗口
该窗口时刻动态变化:当接收到来自发送端的数据时,窗口大小就减小,但是当接收端应用从缓冲区中读取数据时,窗口大小就增大。(UDP不提供流量控制)

TCP连接是全双工的。这意味着在一个给定的连接上应用可以在任何时刻在进出两个方向上既发送数据又接收数据。因此,TCP必须为每个数据流方向跟踪诸如序列号和通告窗口大小等状态信息。建立一个全双工连接后,需要的话可以把它转换成一个单工连接。(见第六章)

SCTP流控制传输协议

SCTP在客户和服务器之间提供关联(一个连接只涉及两个IP地址之间的通信,而一个关联指代两个系统之间的一次通信,它可能因为SCTP支持多宿而涉及不止两个地址)。

与TCP不同的是,SCTP是面向消息的。它提供各个记录的按序递送服务。与UDP一样,由发送端写入的每条记录的长度随数据一道传递给接收端应用。

SCTP能够在所连接的端点之间提供多个流,各个流各自可靠地按序递送消息。一个流上某个消息不会阻塞同一关联其他流上消息的传递。这种做法与TCP正好相反,就TCP而言,在单一字节流中任何位置的字节丢失都将阻塞该连接上其后所有数据的递送,直到该丢失被修复为止。

SCTP还提供多宿特性,使得单个SCTP端点能够支持多个IP地址。该特性可以增强网络故障的健壮性。

TCP连接的建立和终止

我们都知道建立一个TCP连接时会发生三次握手,那具体是什么情况呢?

1.服务器必须准备好接受外来的连接,这通常通过socket、bind、listen这三个函数来完成。我们称之为被动打开
2.客户通过调用connect发起主动打开。这导致客户TCP发送一个SYN(同步)分节,它告诉服务器客户将在连接中发送的数据的初始序列号。通常SYN分节不携带数据,其所在的IP数据报只含有一个IP首部、一个TCP首部及可能有的TCP选项。
3.服务器必须确认(ACK)客户的SYN,同时自己也得发送一个SYN分节,它含有服务器将在同一连接中发送的数据的初始序列号。服务器在单个分节中发送SYN和对客户SYN的ACK(确认)。ACK中的确认号是发送这个ACK的一段所期待的下一个序列号。因为SYN占据一个字节的序列号空间,所以每一个SYN的ACK中的确认号就是该SYN的初始序列号加1。类似的,每一个FIN(表示结束)的ACK中的确认号为该FIN的序列号加1。
4.客户必须确认服务器的SYN。
这种交换至少需要3个分组,因此称之为TCP的三次握手

TCP选项

  • MSS选项
    发送SYN的TCP一段使用本选项通告对端它的最大分节大小-MSS。发送端TCP使用接收端的MSS值作为所发送分节的最大大小。使用TCP_MAXSEG套接字选项提取和设置这个TCP选项。
  • 窗口规模选项
    TCP连接任何一端能够通告对端的最大窗口大小是65535,因为在TCP首部中对应的字段占16位。使用SO_RCVBUF套接字选项影响这个TCP选项。
  • 时间戳选项
    这个选项对于高速网络连接是必要的,他可以防止由失而复现的分组可能造成的数据损坏。

既然高带宽或长延迟的网络被称为“长胖管道”,后两个选项也称为“长胖管道选项”。

TCP连接终止

TCP建立一个连接需3个分节,终止一个连接则需要4个分节。(四次挥手)

  1. 某个应用进程首先调用close,我们称该端执行主动关闭,该端的TCP于是发送一个FIN分节,表示数据发送完毕。
  2. 接收到这个FIN的对端执行被动关闭。这个FIN由TCP确认。它的接收也作为一个文件结束符传递给接收端应用进程(放在已排队等候该应用进程接收的任何其他数据之后),因为FIN的接收意味着接收端应用进程在相应连接上再无额外数据可接受。
  3. 一段时间后,接收到这个文件结束符的应用进程将调用close关闭它的套接字。这导致它的TCP也发送一个FIN。
  4. 接收这个最终FIN的原发送端TCP(即执行主动关闭的一端)确认这个FIN。
  5. 某些情形下步骤1的FIN随数据一起发送,另外步骤2和步骤3发送的分节都出自执行被动关闭的一端,有可能被合并成一个分节。

类似SYN,一个FIN也占据1个字节的序列号空间,每个FIN的ACK确认号就是这个FIN的序列号加1。
在步骤2和步骤3之间,从执行被动关闭一端到执行主动关闭一端流动数据是可能的,称为半关闭。
无论是客户还是服务器,任何一端都可以执行主动关闭,通常情况是客户执行关闭,但是某些协议(譬如值得注意的HTTP/1.0)却由服务器执行主动关闭。

TCP状态转换图

(后续补充)

TIME_WAIT状态

该端点停留在这个状态的持续时间是最长分节生命期(MSL)两倍,有时候称为2MSL。
MSL是任何IP数据报能够在因特网中存活的最长时间。
TIME_WAIT状态有两个存在的理由:

  1. 可靠的实现TCP全双工连接的终止
  2. 允许老的重复分节在网络中消逝。

端口号

支持FTP的任何TCP/IP实现都把21这个众所周知的端口分配给FTP服务器,分配给TFTP的是UDP端口号69。

  • 套接字对
    一个TCP连接的套接字对是一个定义该连接的两个端点的四元组:本地IP地址、本地TCP端口号
    外地IP地址、外地TCP端口号。标识每个端点的两个值(IP地址和端口号)通常称为一个套接字。

TCP端口号与并发服务器

并发服务器中主服务器循环通过派生一个子进程来处理每个新的连接。TCP无法仅仅通过查看目的端口号来分离外来的分节到不同端点。它必须查看套接字对的所有4个元素才能确定由哪个端点接收某个到达的分节。

缓冲区大小及限制

  • IPv4数据报的最大大小是65535字节,包括IPv4首部。总长度字段占据16位。

  • IPv6数据报的最大大小是65575字节,包括40字节的IPv6首部,注意,IPv6的净荷长度字段不包括IPv6首部,而IPv4的总长度字段包括IPv4首部。IPv6有一个特大净荷选项,它把净荷长度字段扩展到32位,不过这个选项需要MTU(最大输出单元)超过65535的数据链路提供支持。

  • 以太网的MTU是1500字节。IPv4要求的最小链路MTU是68字节。IPv6要求的最小链路MTU位1280字节。

  • 在两个主机之间的路径中最小的MTU称为路径MTU,1500字节的以太网MTU是当今常见的路径MTU。

  • 当一个IP数据报将从某个接口送出时,如果它的大小超过相应链路的MTU,IPv4和IPv6都将执行分片,这些片段在到达最终目的地之前通常不会被重组。IPv4主机对其产生的数据报执行分片,IPv4路由器则对其转发的数据报执行分片。然而IPv6只有主机对其产生的数据报执行分片,IPv6路由器不对其转发的数据报执行分片。
    注:一个标记为IPv6路由器的设备可能执行分片,不过知识对于那些由它产生的数据报,而绝不是对于那些由它转发的数据报。由路由器的Telnet服务器产生的IP数据报是由路由器产生的,而不是由路由器转发的。

  • IPv4首部的“不分片”位(即DF位)若被设置,那么不管是发送这些数据报的主机还是转发它们的路由器,都不允许对它们分片。当路由器接收到一个超过其外出链路MTU大小且设置来DF位的IPv4数据报时,它将产生一个ICMPv4出错消息(目的地不可达,需分片但DF位已设置)。

  • TCP有一个MSS,目的是告诉对端其重组缓冲区大小的实际值,从而试图避免分片。MSS经常设置成MTU减去IP和TCP首部的固定长度。在以太网中使用IPv4的MSS值位1460,使用IPv6的MSS值为1440(两者的TCP首部都是20个字节,但IPv4首部是20字节,IPv6首部却是40字节)

TCP输出

每一个套接字有一个发送缓冲区,我们可以使用SO_SNDBUF套接字选项来更改该缓冲区的大小。如果套接字的发送缓冲区容不下该应用进程的所有数据,该应用进程将被投入睡眠,默认设置为阻塞的。从写一个TCP套接字的write调用成功返回仅仅表示我们可以重新使用原来的应用进程套接字,并不表明对端的TCP或应用进程已接收到数据。

UDP输出

任何UDP套接字都有发送缓冲区大小,不过他仅仅是可以写到该套接字的UDP数据报的大小上限。如果一个应用进程写一个大于套接字发送缓冲区大小的数据报,内核将返回该进程一个EMSGSIZE错误。既然UDP是不可靠的,它不必保存应用进程数据的一个副本,因此无需一个真正的发送缓冲区(应用进程的数据在沿协议栈向下传递时,通常被复制到某种格式的一个内核缓冲区中,然而当该数据被发送之后,这个副本就被数据链路层丢弃了)。
如果某个UDP应用进程发送大数据报,那么它们相比TCP应用数据

猜你喜欢

转载自blog.csdn.net/weixin_37778713/article/details/105386870