TCP和UDP概述

《UNIX Network Programming Volume1: The Socket Networking API, Third Edition》
W.Richard Stevens / Bill Fenner / Andrew M.Rudoff

TCP和UDP概述
多字节整数字节序(小端/大端)
套接字I/O
套接字选项
TCP客户/服务器
UDP客户/服务器
广播与多播
ICMP协议与ping

TCP协议经典rfc主题总结

OSI模型

计算机通信开放系统互连(open systems interconnection)模型用于描述一个网络中各个协议层。这是一个七层模型,下图给出了它与网际协议族的近似映射:

  • 数据链路层和物理层是随系统提供的设备驱动程序和网络硬件。通常只需知道数据链路的某些特性(如1500字节以太网的MTU大小)。
  • 网络层由IPv4和IPv6两个协议处理。传输层有TCP或UDP(其间有间隙,表明网络应用可以使用原始套接字绕过传输层,甚至网络层)。
  • OSI模型的顶上三层是浏览器、FTP服务器、Telnet客户等网络应用所在的层,对于网际协议,这三层协议几乎没有区别。
  • 套接字编程接口是从顶上三层进入传输层的接口。顶上三层通常构成用户进程,底下四层通常作为操作系统内核的一部分提供。

TCP/IP协议族

虽然协议族被称为“TCP/IP”,但除了这两个主要协议外,还有许多其他成员。部分如下:

IPv4——网际协议版本4(Internet Protocol version 4)。使用32位地址。
IPv6——网际协议版本6(Internet Protocol version 6)。使用128位地址以应对因特网的爆发性增长。
TCP——传输控制协议(Transmission Control Protocol)。TCP是一个面向连接的协议,为用户进程提供可靠的全双工字节流。TCP套接字是一种流套接字(stream socket)。TCP关心确认、超时和重传之类的细节。
UDP——用户数据报协议(User Datagram Protocol)。UDP是一个无连接协议。UDP套接字是一种数据报套接字(datagram socket)。UDP数据报不能保证最终到达它们的目的地。
ICMP——网际控制消息协议(Internet Control Message Protocol)。ICMP处理在路由器和主机之间流通的错误和控制消息。ping和traceroute程序使用此协议。
ARP——地址解析协议(Address Resolution Protocol)。ARP把一个IPv4地址映射成一个硬件地址(如以太网地址)。ARP通常用于广播网络。
RARP——反向地址解析协议(Reverse Address Resolution Protocol)。RARP把一个硬件地址映射成一个IPv4地址。

用户数据报协议(UDP)

应用进程往一个UDP套接字写入一个消息,该消息被封装到一个UDP数据报,该UDP数据报进而又被封装到一个IP数据报,然后发送到目的地。UDP不保证UDP数据报会到达其最终目的地,不保证各个数据报的先后顺序跨网络后保持不变,也不保证每个数据报只到达一次。

  • 每个UDP数据报都有一个长度。如果一个数据报正确地到达其目的地,那么该数据报的长度将随数据一道传递给接收端应用进程。而TCP是一个字节流(byte-stream)协议,没有任何记录边界,这一点不同于UDP。
  • UDP提供无连接(connectionless)的服务。举例来说,一个UDP客户可以创建一个套接字并发送一个数据报给一个给定的服务器,然后立即用同一个套接字发送另一个数据报给另一服务器。同样地,一个UDP服务器可以用同一个UDP套接字从若干个不同的客户接收数据报,每个客户一个数据报。

传输控制协议(TCP)

TCP提供客户与服务器之间的连接,TCP客户先与某个给定服务器建立一个连接,再跨该连接与那个服务器交换数据,然后终止这个连接。

  • TCP提供可靠性。当TCP向另一端发送数据时,它要求对端返回一个确认。如果没收到确认,TCP就自动重传数据并等待更长时间,在数次重传失败后,TCP才放弃
  • TCP含有动态估算客户与服务器之间的往返时间(round-trip time,RTT)的算法。以便它知道等待一个确认需要多长时间。
  • TCP通过给其中每个字节关联一个序列号对所发送的数据进行排序(sequencing)。举例来说,假设一个应用写2048字节到一个TCP套接字,导致TCP发送两个分节(分节是TCP传递给IP的数据单元):第一个分节所含数据的序列号为1~1024,第二个分节所含数据的序列号为1025~2048。如果这些分节非顺序到达,接收端TCP将先根据它们的序列号重新排序,再把结果数据传递给接收应用。如果接收端TCP接收到来自对端的重复数据(网络通信拥挤重传时),可以根据分节序列号判定数据是重复的,从而丢弃重复数据。
  • TCP提供流量控制(flow control)。 TCP总是告知对端在任何时刻它一次能够从对端接收多少字节的数据,这称为“通告窗口(advertised window)”。在任何时刻,该窗口指出接收缓冲区中当前可用的空间量,从而确保发送端发送的数据不会使接收缓冲区溢出。通告窗口大小减少到0是可能的:当TCP对应某个套接字的接收缓冲区已满,导致它必须等待应用从该缓冲区读取数据时,方能从对端再接收数据。
  • TCP连接是全双工的(full-duplex)。这意味着在一个给定的连接上应用可以在任何时刻在进出两个方向上既发送数据又接收数据

TCP选项

  • MSS选项——发送SYN的TCP一端使用本选项通告对端它的最大分节大小(maximum segment size)即MSS,也就是它在本连接的每个TCP分节中愿意接受的最大数据量。可使用TCP_MAXSEG套接字选项提取和设置这个TCP选项。
  • 窗口规模选项——TCP连接任何一端能够通告对端的滑动窗口大小(接收缓冲区大小),因为在TCP首部中缓冲区大小字段占16位,所以它的最大值是65535。对于一些情况(光纤高速通信网络,或者是卫星长连接网络)来说需要使用更大的滑动窗口,这时会使用扩展的滑动窗口大小(要求有更大的窗口以获得尽可能大的吞吐量)。
  • 时间戳选项——对于高速网络连接是必要的,可防止由暂时的路由原因造成的迷途的分组可能造成的数据损坏。

TCP的首部

  • 每个TCP段都包含源端和目的端的端口号,用于寻找发端和收端应用进程。这两个值加上IP首部中的源端IP地址和目的端IP地址唯一确定一个TCP连接。
  • 在TCP首部中有 6个标志比特。它们中的多个可同时被设置为 1。
    • URG 紧急指针(urgent pointer)有效
    • ACK 确认序号有效
    • PSH 接收方应该尽快将这个报文段交给应用层
    • RST 重建连接
    • SYN 同步序号用来发起一个连接
    • FIN 发端完成发送任务

TCP状态转换

TCP建立一个连接需3个分节,终止一个连接则需4个分节,涉及连接建立和连接终止的操作可以用状态转换图来说明。TCP为一个连接定义了11中状态,并且规定如何基于当前状态及在该状态下所接收的分节从一个状态转换到另一个状态。(可使用netstat去监视状态变化)

  • ESTABLISHED状态引出的两个箭头处理连接的终止。如果某个应用进程在ESTABLISHED状态期间接收到一个FIN(被动关闭),那就转换到CLOSE_WAIT状态;如果在接收到一个FIN之前调用close(主动关闭),那就转换到FIN_WAIT_1状态。

一个完整的TCP连接所发生的实际分组交换情况包括:连接建立、数据传送和连接终止。下图展示了分组交换过程中每个端点所经历的TCP状态,客户端通告一个值为536的MSS(最小重组缓冲区大小),服务器通告一个值为1460的MSS(以太网上IPv4的典型值):

WAIT_TIME状态

执行主动关闭的一端经历了这个状态。该端点停留在这个状态的持续时间是最长分节生命期(maximum segment lifetime, MSL)的两倍,有时称为2MSL。任何TCP实现都必须为MSL选择一个值,RFC 1122建议值为2分钟,源自Berkeley的实现传统上改用30秒。这意味着TIME_WAIT状态的持续时间在1分钟到4分钟之间

网络中,一个TCP分节可能由路由异常(某个路由器崩溃或某两个路由器之间的某个链路断开时)导致”迷途“,迷途的TCP分节自其开始旅程起需要最多MSL秒内路由方能修复。如果在迷途期间,发送端TCP超时并重传TCP分节,重传的TCP分节和之前迷途的TCP分节都可能被正确送达目的地。TCP必须正确处理这种情况。

图”TCP连接的分组交换“为例,如果上述情况发生在一个TCP连接终止序列4个分节中的最终的ACK分节上时,导致客户端最终的ACK丢失,服务端将重新发送它的最终的FIN,因此客户端必须维护状态信息(TIME_WAIT)等待路由修复,以允许它重新发送最终的ACK。(TCP要可靠地实现全双工连接的终止,必须正确处理连接终止序列4个分节中任何一个分节丢失的情况。)本例也说明了为什么执行主动关闭的那一端是处于TIME_WAIT状态的一端:因为可能不得不重传最终那个ACK的就是执行主动关闭的那一端。

假设12.106.32.254:1500和206.168.112.219:21之间有一个TCP连接,当关闭这个连接时出现了上述情况,TCP必须防止来自某个连接的老的重复分组在该连接已终止后再现,从而被误解成属于同一连接的某个新的化身。为做到这一点,TCP将不给处于TIME_WAIT状态的连接发起新的化身。既然TIME_WAIT状态的持续时间是MSL的2倍,这就足以让某个方向上的分组最多存活MSL秒即被丢弃,另一个方向上的应答最多存活MLS秒也被丢弃。通过这个规则就能保证,每成功建立一个TCP连接时,来自该连接先前化身的老的重复分组都已在网络中消逝了

端口号

16位整数表示端口号(port number)。
IANA(the Internet Assigned Numbers Authority,因特网已分配数值权威机构)维护着一个端口号分配状况的清单。端口号被划分成以下3段:

  1. 众所周知的端口为0~1023。这些端口由IANA分配和控制。例如Web服务器为80、FTP服务器为21、TFTP的UDP端口为69等
  2. 已登记端口(registered port)为1024~49151。这些端口不受IANA控制,不过由IANA登记并提供它们的使用情况清单。例如**6000~6063分配给X Window服务器。**49151这个上限的引入是为了给临时端口留出范围。
  3. 动态(dynamic)或临时端口为49151~65535。IANA不管这些端口。(49151这个魔数是65535的四分之三。

  • Unix系统有保留端口(reserved port)的概念,指的是小于1024的任何端口(所有IANA众所周知的端口都是保留端口),分配使用这些端口的服务器必须以超级用户特权启动。
  • 由于历史原因,源自Berkeley的实现(从4.3BSD开始)曾在1024~5000范围内分配使用临时端口,使得早期主机在任何给定时间内同时最多支持3977个连接。
  • 有少数客户端(rlogin和rsh客户)需要一个保留端口用于客户/服务器的认证,这些客户调用库函数rresvport(从1023到513尝试绑定端口)创建TCP套接字,并赋予一个在513~1023范围内未使用的端口。

缓冲区大小及限制

  • 许多网络有一个可由硬件规定的MTU。举例来说,以太网的MTU是1500字节。IPv4要求的最小链路MTU是68字节。IPv6要求的最小链路MTU为1280字节。
  • IPv4和IPv6都定义了最小重组缓冲区大小(minimum reassembly buffer size),它是IPv4或IPv6的任何实现都必须保证支持的最小数据报大小,对于IPv4为576字节,对于IPv6为1500字节。另外,IPv4数据报的最大大小是65535字节(包括IPv4首部),IPv6数据报的最大大小是65575字节(包括40字节的IPv6首部)。
  • TCP有一个MSS(maximum segment size,最大分节大小),用于向对端TCP通告对端在每个分节中能发送的最大TCP数据量。MSS的目的是告诉对端其重组缓冲区大小的实际值,从而避免分片。MSS经常设置成MTU减去IP和TCP首部的固定长度。

TCP输出

每一个TCP套接字有一个发送缓冲区,可使用SO_SNDBUF套接字选项来更改该缓冲区的大小。下图假设该套接字是阻塞的(通常的默认设置):

当某个应用进程调用write时,内核从该应用进程的缓冲区中复制所有数据到所写套接字的发送缓冲区。如果该套接字的发送缓冲区容不下该应用进程的所有数据,该应用进程将被投入睡眠,内核将不从write系统调用返回,直到应用进程缓冲区中的所有数据都复制到套接字发送缓冲区。

当write成功返回后,本端TCP提取套接字发送缓冲区中的数据并把它发送给对端TCP(其过程基于TCP数据传送的所有规则),对端TCP必须确认收到的数据,伴随来自对端的ACK的不断到达,本端TCP至此方能从套接字发送缓冲区中丢弃已确认的数据。

UDP输出

任何UDP套接字都有一个发送缓冲区大小,可使用SO_SNDBUF套接字选项来更改它,不过它仅仅是可写到该套接字的UDP数据报的大小上限,而发送缓冲区本身实际上并不存在。下图为写UDP套接字的过程:

如果一个应用进程写一个大于该套接字发送缓冲区大小的数据报,内核将返回该进程一个EMSGSIZE错误。 既然UDP是不可靠的,因此无需一个真正的发送缓冲区。(应用进程的数据沿协议栈向下传递时,通常被复制到某种格式的一个内核缓冲区中,然后当该数据被发送之后,这个副本就被数据链路层丢弃了。)

本端UDP简单地给来自用户的数据报安上8字节的首部以构成UDP数据报,然后传递给IP。IPv4和IPv6给UDP数据报安上相应的IP首部以构成IP数据报,执行路由操作确定外出接口,然后或者直接把数据报加入数据链路层输出队列(如果适合于MTU),或者分片后再把每个分段加入数据链路层的输出队列。由于TCP会把应用数据划分成MSS大小的块,而UDP却没有对等的手段,当某个UDP应用进程发送大数据报(如2000字节的数据报)时,UDP相比TCP应用数据更有可能被分片。

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

常见因特网应用的协议

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值