TCP端口号与并发服务器,缓冲区大小限制,TCP/UDP输出机制

本文详细阐述了TCP和UDP在网络传输中的工作机制,包括TCP如何通过分段和确认确保可靠传输,UDP如何处理数据报的发送及可能的分片情况。此外,还介绍了TCP和UDP在发送缓冲区管理方面的差异。

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

TCP端口号与并发服务器

        并发服务器中主服务器循环通过派生一个子进程来处理每个新的连接。

        当服务器接收并接受这个客户的连接时,它fork一个自身的副本,让子进程来处理该客户的请求。TCP无法仅仅通过查看目的端口号来分离外来的分节到不同的端点,它必须查看套接字对的所有4个元素才能确定由哪个端点接收某个到达的分节。

缓冲区大小及限制

影响IP数据报大小的限制有哪些?

        (1) IPv4数据报的最大大小是65535字节,包括IPv4首部。因为其总长度字段占据16位(2^16-1)。

        (2) IPv6数据报的最大大小是65575字节,包括40字节的IPv6首部。因为其净荷长度字段占据16位,但是IPv6的净荷长度字段不包括IPv6首部。

        (3) 许多网络有一个可由硬件规定的MTU。例如,以太网的MTU是1500字节。IPv4要求的最小链路MTU是68字节,这允许最大的IPv4首部(包括20字节的固定长度部分和最多40字节的选项部分)拼接最小的片段(IPv4首部中片段偏移字段以8个字节为单位)。

        (4) 在两个主机之间的路径中最小的MTU称为路径MTU(path MTU)。1500字节的以太网MTU是当今常见的路径MTU。两个主机之间相反的两个方向上路径MTU可以不一致,因为在因特网中路由选择往往是不对称的。也就是说从A到B和从B到A的路径可以不相同。

        (5) 当一个IP数据报将从某个接口送出时,如果它的大小超过相应链路的MTU,IPv4和IPv6都将执行分片(fragmentation)。这些片段在到达最终目的地之前通常不会被重组(reassembling)。IPv4主机对其产生的数据报执行分片,IPv4路由器则对其转发的数据报执行分片。

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

IPv4的DF位可用于路径MTU发现。例如,如果基于IPv4的TCP使用该技术,那么它将在所发送的所有数据报中设置DF位,如果某个中间路由器返回一个ICMP“destination unreachable, fragmentation needed but DF bit set”错误,TCP就减小每个数据报的数据量并重传。路径MTU发现对于IPv4是可选的。

注意:

路径MTU发现在如今的因特网上是有问题的,因为许多防火墙丢弃所有ICMP消息,包括用于路径MTU发现的上述消息。这意味着TCP永远得不到要求它降低所发送数据量的信号。IETF已经开始尝试定义不依赖于ICMP出错消息的另一种路径MTU发现方法。

        (7) IPv4和IPv6都定义了最小重组缓冲区大小(minimum reassembly buffer size),它是IPv4或IPv6的任何实现都必须保证支持的最小数据报大小。其值对于IPv4为576字节,对于IPv6为1500字节。

        (8) TCP有一个MSS(maximum segment size,最大分节大小),用于向对端TCP通告对端在每个分节中能发送的最大TCP数据量。SYN分节上有MSS选项,MSS的目的是告诉对端其重组缓冲区大小的实际值,从而试图避免分片。

MSS经常设置成 = MTU - (IP和TCP首部的固定长度)= 1500 - (20+20)= 1460

在以太网中使用IPv4的MSS值为1460。

在TCP的MSS选项中,MSS值是一个16位的字段,限定其最大值为65535。这对于IPv4是合适的,因为IPv4数据报中的最大TCP数据量为65495 = 65535 - (20+20)

TCP输出

某个应用进程写数据到一个TCP套接字中时发生的步骤:

        [1] 每一个TCP套接字有一个发送缓冲区,可以使用SO_SNDBUF套接字选项来更改该缓冲区的大小。

        [2] 当某个应用进程调用write时,内核从该应用进程的缓冲区中复制所有数据到所写套接字的发送缓冲区。

        [3] 如果该套接字的发送缓冲区容不下该应用进程的所有数据(或是应用进程的缓冲区大于套接字的发送缓冲区,或是套接字的发送缓冲区中已有其他数据),该应用进程将被投入睡眠。——这里假设该套接字是阻塞的(默认设置),内核将不从write系统调用返回,直到应用进程缓冲区中所有数据都复制到套接字发送缓冲区。

注意:因此,从写一个TCP套接字的write调用成功返回仅仅表示我们可以重新使用原来的应用进程缓冲区,并不表明对端的TCP或应用进程已经接收到了数据。

        [4] 这一端的TCP提取套接字发送缓冲区中的数据并把它发送给对端TCP,其过程基于TCP数据传送的所有规则,对端TCP必须确认收到的数据。伴随来自对端的ACK的不断达到。本端TCP至此才能从套接字发送缓冲区中丢弃已经确认的数据,即,接收端确认完,发送端才可以丢弃发送缓冲区中的已确认的数据,TCP必须为已发送的数据保留一个副本,直到它被对端确认为止。

        [5] 发送端TCP以通知的MSS大小的或更小的块把数据传递给IP,同时给每个数据块安上一个TCP首部以构成TCP分节,其中MSS或是由对端通告的值,或是536(若对端未发送一个MSS选项)

注意:536 = IPv4最小重组缓冲区字节数576 – (Ipv4首部字节数20 + TCP首部字节数20)

IP给每个TCP分节安上一个IP首部构成IP数据报,并按照其目的IP地址查找路由表项以确定外出接口,然后把数据报传递给相应的数据链路。

        [6] IP可能在把数据报传递给数据链路之前将其分片,不过MSS选项的目的之一就是试图避免分片,较新的实现还使用了路径MTU发现功能。

        [7] 每个数据链路都有一个输出队列,如果该队列已满,那么新到的分组将被丢弃,并沿协议栈向上返回一个错误:从数据链路 => IP => TCP,TCP将注意到这个错误,并在以后某个时刻重传相应的分节。应用进程并不知道这种暂时的情况。

UDP输出

某个应用进程写数据到一个UDP套接字中时发生的步骤:

        [1] UDP的发送缓冲区实际上是不存在的

        [2] 任何UDP套接字都有发送缓冲区大小(可以使用SO_SNDBUF选项修改),不过它仅仅是可写到该套接字的UDP数据报的大小上限。如果一个应用进程写一个大于套接字发送缓冲区大小的数据报,内核将返回该进程一个EMSGSIZE错误。

        [3] 既然UDP是不可靠的,它不必保存应用进程数据的一个副本,因此无需一个真正的发送缓冲区。(应用进程的数据在沿协议栈向下传递时,通常被复制到某种格式的一个内核缓冲区中,然后当该数据被发送之后,这个副本就被数据链路层丢弃了。)

        [4] 发送端的UDP给来自用户的数据报安上它的8字节的首部以构成UDP数据报,然后传递给IP。IPv4或IPv6给UDP数据报安上相应的IP首部以构成IP数据报,执行路由操作确定外出接口,然后或者直接把数据报加入数据链路层输出队列(如果适合于MTU),或者分片后再把每个片段加入数据链路层的输出队列。

        注意:如果某个UDP应用进程发送大数据报(譬如说2000字节的数据报),那么它们相比TCP应用数据更有可能被分片,因为TCP会把应用数据划分成MSS大小的块,而UDP却没有对等的手段。

[5]从写一个UDP套接字的write调用成功返回,表示所写的数据报或其所有片段已被加入数据链路层的输出队列。如果该队列没有足够的空间存放该数据报或它的某个片段,内核通常会返回一个ENOBUFS错误给它的应用进程。

        注意:不幸的是,有些UDP的实现不返回这种错误,这样甚至数据报未经发送就被丢弃的情况应用进程也不知道。

 

SCTP输出

某个应用进程写数据到一个TCP套接字中时发生的步骤:

        [1] 每一个套接字有一个发送缓冲区,可以使用SO_SNDBUF套接字选项来更改该缓冲区的大小。

        [2] 当某个应用进程调用write时,内核从该应用进程的缓冲区中复制所有数据到所写套接字的发送缓冲区。

        [3] 如果该套接字的发送缓冲区容不下该应用进程的所有数据(或是应用进程的缓冲区大于套接字的发送缓冲区,或是套接字的发送缓冲区中已有其他数据),该应用进程将被投入睡眠。——这里假设该套接字是阻塞的(默认设置),内核将不从write系统调用返回,直到应用进程缓冲区中所有数据都复制到套接字发送缓冲区。

注意:因此,从写一个TCP套接字的write调用成功返回仅仅表示我们可以重新使用原来的应用进程缓冲区,并不表明对端的TCP或应用进程已经接收到了数据。

        这一端的SCTP提取套接字发送缓冲区中的数据并把它发送给对端SCTP,其过程基于SCTP数据传送的所有规则。本端SCTP必须等待SACK,在累积确认点超过已发送的数据后,才可以从套接字缓冲区中删除出该数据。

参考:(UNP点滴记录) TCP端口号与并发服务器,缓冲区大小限制,TCP/UDP输出机制_delphiwcdj的专栏-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值