Unix网络编程

TCP、UDP和SCTP

UDP是一个简单的,不可靠的数据报协议。应用进程往一个UDP套接字写入一个消息,该消息随后被封装到一个UDP数据报,该UDP数据报进而又被封装到IP数据报,然后发送到目的地。UDP不保证UDP数据报会到达其最终目的地,不保证各个数据报的先后顺序跨网络后保持不变,也不保证每个数据报只到达一次。
每个UDP数据报都有一个长度,如果一个数据报正确地到达其目的地,那么该数据报的长度将随数据一道传递给接收端应用进程。


TCP是一个复杂、可靠的字节流协议。当TCP向另一端发送数据时,它要求对端返回一个确认。如果没有收到确认,TCP就自动重传数据并等待更长时间,在数次重传失败后,TCP才放弃,如此在尝试发送数据上所花的总时间一般为4~10分钟(依赖于具体实现)。
TCP含有用于动态估算客户和服务器之间的往返时间RTT的算法,以便它知道等待一个确认需要多少时间。TCP通过给其中每个字节关联一个序列号对所发送的数据进行排序,接收端TCP将先根据它们的序列号重新排序,再把结果数据传递给接收应用。
TCP提供流量控制。TCP总是告知对端在任何时刻它一次能够从对端接收多少字节的数据,这称为通告窗口。在任何时刻,该窗口之处接受缓冲区中当前可用的空间量,从而确保发送端发送端数据不会使接收缓冲区溢出。该窗口时刻动态变化:当接收到来自发送端到数据时,窗口大小就减小,但是当接收端应用从缓冲区中读取数据时,窗口大小就增大。当TCP对应某个套接字的接收缓冲区已满,导致它必须等待应用从该缓冲区读取数据时,方能从对端再接收数据。
TCP连接是全双工的,TCP必须为每个数据流方向跟踪诸如序列号和通告窗口大小等状态信息。建立一个全双工连接后,需要的话可以把它转换成一个单工连接。


SCTP与TCP类似之处在于它也是一个可靠的传输协议,但它还提供消息边界、传输级别多宿(multtihoming)支持以及将头端阻塞(head-of- line- blocking)减少到最小的一种方法。
SCTP是面向消息的,它提供各个记录的按递送服务。和UDP一样,由发送端写入的每条记录的长度随数据一道传递给接收端应用。
SCTP能够在所连接的端点之间提供多个流,每个流各自可靠地按序递送消息。一个流上某个消息的丢失不会阻塞同一关联其他流上消息的投递。
SCTP还提供多宿特性,使得单个SCTP端点能够支持多个IP地址。该特性可以增强应对网络故障的健壮性。一个端点可能有多个冗余的网络连接,每个网络又可能有各自接入因特网基础设施的连接。当该端点与另一个端点建立一个关联后,如果它的某个网络或某个跨越因特网的通路发生故障,SCTP就可以通过切换到使用已与该关联相关的另一个地址来规避所发生的故障。

三路连接

1.服务器必须准备好接受外来的连接。这通常调用socket、bind和listen这3个函数来完成,称之为被动打开。
2.客户通过调用connect发起主动打开。这导致客户TCP发送一个SYN分节,它告诉服务器客户将在(待建立的)连接中发送的数据的初始序列号。通常SYN分节不携带数据,其所在IP数据报只含有一个IP首部及可能有的TCP选项。
3.服务器必须确认(ACK)客户的SYN,同时自己也得发送一个SYN分节,它含有服务器将在同一连接中发送的数据的初始序列号。服务器在单个分节中发送SYN和对客户SYN的ACK。
4.客户必须确认服务器的SYN。

TIME_WAIT状态

最长分节生命周期MSL
任何TCP实现都必须为MSL选择一个值。MSL是任何IP数据报能够在因特网中存活的最长时间。
TIME_WAIT状态有两个存在的理由:
1.可靠地实现TCP全双工连接的终止
2.允许老的重复分节在网络中消逝。

SCTP关联的建立和终止

四路握手

1.服务器必须准备好接受外来的关联。这通常调用socket、bind和listen这3个函数来完成,称之为被动打开。
2.客户通过调用connect或发送一个隐式打开该关联发起主动打开。这导致客户SCTP发送一个INIT分节,它告诉服务器客户的IP地址清单、初始序列号、用于标识本关联中所有分组的起始标识、客户请求的外出流的树木以及客户能够支持的外来流的数目。
3.服务器以一个INIT ACK消息确认客户的INIT消息,其中含有服务器的IP地址清单、初始序列号、起始标记、服务器请求的外出流的数目、服务器能够支持的外来流的数目以及一个状态cookie。状态cookie包含服务器用于确信本关联有效所需的所有状态,它是数字化签名过的,以确保其有效性。
4.客户以一个COOKIE ACK消息确认客户回射的cookie是正确的,本关联于是建立。该消息也可能在同一个分组中还捆绑了用户数据。

SCTP的四路握手类似于TCP的三路握手,差别主要在于作为SCTP整体一部分的cookie的生成。INT承载一个验证标记Ta和一个初始序列号J。在关联的有效期内,验证标记Ta必须在对端发送端每个分组中出现。初始序列号J用作承载用户数据的DATA块的起始序列号。对端也在INT ACK中承载一个演这个标记Tz,在关联的有效期内,验证标记Tz也必须在其发送的每个分组中出现。除了验证标记Tz和初始序列号K外,INIT的接收端还在作为响应的INIT ACK中提供一个cookie C。该cookie包含设置本SCTP关联所需的所有状态,这样服务器端的SCTP栈就不必保持所关联客户的有关信息。
四手握手过程结束时,两端各自选择一个主目的地址,当不存在网络故障时,主目的地址将用作数据要发送到的默认目的地。

SCTP不像TCP那样允许“半关闭”的关联。当一段关闭某个关联时,另一端必须停止发送新的数据。关联关闭请求的接收端发送完已经排队的数据后,完成关联的关闭。
SCTP没有类似于TCP的TIME_WAIT状态,因为SCTP使用了验证标记。所有后续块都在捆绑它们的SCTP分组的公共首部标记了初始的INIT块和INIT ACK块中作为起始标记交换的验证标记。由来自旧连接的块通过所在SCTP分组的公共首部简介携带的验证标记对于新连接来说是不正确的。因此,SCTP通过放置验证标记值就避免了TCP在TIME_WAIT状态保持整个连接的做法。

套接字对

一个tcp连接的套接字对是一个定义该连接的两个端点的四元组:本地IP地址、本地TCP端口号、外地IP地址、外地TCP端口号。套接字对唯一标识一个网络上的每个TCP连接。就SCTP而言,一个关联由一组本地IP地址、一个本地端口、一组外地IP地址、一个外地端口标识。在两个端点均非多宿的简单情形下,SCTP与TCP所用的四元套接字对一致。然而在某个关联的任何一个端点为多宿的情形下,同一个关联可能需要多个四元组表示(这些四元组的IP地址各不相同,但端口号是一样的)。
标识每个端点的两个值(IP地址和端口号)通常称为一个套接字。

TCP端口号与并发服务器

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

缓冲区大小及限制

IPv4数据报的最大大小是65535字节,包括IPv4首部。
IPv6数据报的最大袋小是65575字节,包括40字节的IPv6首部
MTU最大传输单元,IPv4要求的最小链路MTU是68字节。这允许最大的IPv4首部(包括20字节的固定长度部分和最多40字节的选项部分)拼接最小的片段(IPv4首部中片段偏移字段以8个字节为单位)。IPv6要求的最小链路MTU为1280字节。IPv6可以运行在MTU小于此最小值的链路上,不过需要特定于链路的分片和重组功能。
在两个主机之间的路径中最小的MTU称为路径MTU。1500字节的以太网MTU是当今常见的路径MTU。
当一个IP数据报将从某个接口送出时,如果它的大小超过相应链路的MTU,IPv4和IPv6都将执行分片。这些片段在到达最终目的地之前通常不会被重组。IPv4主机对其产生的数据报执行分片,IPv6路由器不对其转发的数据报执行分片。
IPv4首部的“不分片”位(即DF位)若被设置,那么不管时发送这些数据报的主机还是转发它们的路由器,都不允许对它们分片。当路由器接收到一个超过其外出链路MTU大小且设置了DF位的IPv4数据报时,将产生一个ICMPv4出错消息。

IPv4和IPv6都定义了最小重组缓冲区大小,它是IPv4或IPv6都任何实现都必须支持的最小数据报大小。其值对IPv4为576字节,对于IPv6为1500字节。
TCP有一个MSS(最大分节大小),用于向对端TCP通告对端在每个分节中能发送端最大TCP数据量。MSS经常设置成MTU减去IP和TCP首部的固定长度。
SCTP基于到对端所有地址发现的最小路径MTU保持一个分片点。这个最小MTU大小用于把较大的用户信息分割成较小的能够以单个IP数据报发送的若干片段。

TCP输出

每个TCP套接字有一个发送缓冲区,当某个应用调用write时,内核从该应用进程的缓冲区中复制所有数据到缩写套接字的发送缓冲区。如果套接字的发送缓冲区容不下该应用进程的所有数据,该应用进程将被投入睡眠。假设该套接字时阻塞的,内核将不从write系统调用返回,知道应用进程缓冲区中的所有数据都复制到套接字发送缓冲区。因此,从写一个TCP套接字的write调用成功返回仅仅表示我们可以重新使用原来的应用进程缓冲区,并不表明对端的TCP或应用进程已接收到数据。这一端端TCP提取套接字发送缓冲区中的数据并把它发送给对端TCP,其过程基于TCP数据传送的所有规则。对端TCP必须确认收到的数据,伴随来自对端的ACK的不断到达,本端TCP致辞才能从套接字发送缓冲区中丢弃已确认的数据。TCP必须为已发送的数据保留一个副本,直到它被对端确认。

UDP输出

每个UDP套接字都有发送缓冲区大小,不过它仅仅是可以写到该套接字的UDP数据报的大小上限。如果一个应用进程写一个大雨套接字发送缓冲区大小的数据报,内核将返回该进程一个EMSGSIZE错误。既然UDP是不可靠的,它不必保存应用进程数据的一个副本,因此无需一个真正的发送缓冲区。(应用进程的数据在沿协议栈向下传递时,通常被复制到某种格式的一个内核缓冲区中,然而当该数据被发送之后,这个副本就被数据链路层丢弃了。)这一端的UDP简单地给用户的数据报安上它的8字节的首部以构成UDP数据报,然后传递给IP。IPv4或IPv6给UDP数据岸上相应的IP首部以构成IP数据报,执行路由操作确定外出接口,然后或者直接把数据报加入数据链路层输出队列,或者分片后再把每个片段加入数据链路层的输出队列。

SCTP输出

SCTP和TCP是类似的可靠协议,它的套接字也有一个发送缓冲区,而且跟TCP一样,当某个应用调用write时,内核从该应用进程的缓冲区中复制所有数据到缩写套接字的发送缓冲区。如果套接字的发送缓冲区容不下该应用进程的所有数据,该应用进程将被投入睡眠。假设该套接字时阻塞的,内核将不从write系统调用返回,知道应用进程缓冲区中的所有数据都复制到套接字发送缓冲区。因此,从写一个SCTP套接字的write调用成功返回仅仅表示我们可以重新使用原来的应用进程缓冲区,并不表明对端的SCTP或应用进程已接收到数据。这一端SCTP提取套接字发送缓冲区中的数据并把它发送给对端SCTP,其过程基于SCTP数据传送的所有规则。对端SCTP必须确认收到的数据,伴随来自对端的ACK的不断到达,本端SCTP至此才能从套接字发送缓冲区中丢弃已确认的数据。SCTP必须为已发送的数据保留一个副本,直到它被对端确认。

基于TCP套接字编程

socket函数

为了执行网络I/O,一个进程必须做的第一件事就是调用socket函数,指定期望的通信协议类型。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值