TCP与UDP连接
看结果请直接拉到底↓
TCP
和UDP
协议是两个不同的协议,用于处理IP网络(Internet)中的客户端之间的数据通信。
在传统OSI
模型中,TCP
和UDP
是传输层协议。其中TCP
是面向连接的协议,而UDP
是无连接协议。
TCP
从理论上讲,传输层协议可以是一个非常简单的,但是不能将TCP协议称为简单协议。为什么要使用与TCP一样复杂的传输层?最重要的原因取决于IP的不可靠性。实际上,TCP下的所有层都不可靠,并且逐跳传递数据报。IP层逐跳传送数据报,并且不能保证传送数据报。这是一个无连接系统。IP只是处理数据报的路由。如果出现问题,IP会立即丢弃该数据包,并在此过程中将错误消息返回给发送方。确定通过网络发送的数据报的状态并在部分已被丢弃的情况下处理信息重发的任务落在TCP上。
大多数用户将TCP和IP视为紧密的对,但是TCP可以并且经常与其他传输协议一起使用。
例如,在文件传输协议(FTP)和简单邮件传输协议(SMTP)中都使用TCP或其中的一部分,它们都不使用IP。
传输控制协议为IP层和上层提供了大量服务。最重要的是,它为上层提供了面向连接的协议,该协议使应用程序可以确保通过网络发送的数据报被完整接收。在此角色下,TCP充当提供可靠通信的消息验证协议。如果数据报已损坏或丢失,则通常由TCP(不是较高层中的应用程序)来处理重传。
TCP管理来自更高层的数据报流,以及来自IP层的传入数据报。它必须确保优先事项和安全得到尊重。TCP必须能够处理其上期望输入数据报的应用程序的终止,以及较低层的故障。TCP还必须维护TCP层内外所有数据流的状态表。将这些服务隔离在一个单独的层中,可以在不考虑流控制或消息可靠性的情况下设计应用程序。没有TCP层,每个应用程序都必须自己实现服务,这是资源的浪费。
TCP位于传输层,位于IP之上,但位于上层及其应用程序之下,如下图所示。TCP仅驻留在实际处理数据报的设备上,以确保数据报已从源计算机传递到目标计算机。它不驻留在仅路由数据报的设备上,因此网关中没有TCP层。这是有道理的,因为在网关上,数据报在分层模型中不需要比IP层更高。
TCP报头结构
TCP段作为Internet数据报发送。Internet协议报头包含几个信息字段,包括源和目标主机地址。TCP头跟随Internet头,提供特定于TCP协议的信息。这种划分允许存在TCP以外的主机级别协议。
1 | 0 1 2 3 |
名称 | 含义 | 长度 |
---|---|---|
Source Port | 源端口号 | 16 |
Destination Port | 目的端口号 | 16 |
Sequence Number | 此段中第一个数据八位位组的序列号(存在SYN时除外)。如果存在SYN,则序列号为初始序列号(ISN),而第一个数据字节为ISN + 1。 | 32 |
Acknowledgment Number | 如果设置了ACK控制位,则该字段包含该段的发送者希望接收的下一个序列号的值。建立连接后,将始终发送该连接。 | 32 |
Data Offset | TCP报头中的32位字的数量。这指示数据从何处开始。TCP头(甚至包括选项在内的一个头)的整数是32位长。 | 4 |
Reserved | 保留以备将来使用。必须为零。 | 6 |
Control Bits | 控制位 — 从左至右 | 6 |
URG | 紧急指针字段意义重大 | 1 |
ACK | 确认字段有效 | 1 |
PSH | 推送功能 | 1 |
RST | 重置连接 | 1 |
SYN | 同步序列号 | 1 |
FIN | 没有来自发件人的更多数据 | 1 |
Window | 此字节的数量以该段的发送方愿意接受的确认字段中指示的位数开始。 | 8 |
Checksum | 校验和字段是标头和文本中所有16位字的一个人的补码之和的16位一个人的补码。如果段中包含奇数个要校验和的标题和文本八位位组,则最后一个八位组将在右边填充零,以形成一个16位字用于校验和。打击垫不作为片段的一部分发送。在计算校验和时,校验和字段本身将替换为零。 校验和还覆盖了概念上以TCP头为前缀的96位伪头。该伪标头包含源地址,目标地址,协议和TCP长度。这样可以为TCP提供保护,以防止路由错误的段。该信息在Internet协议中承载,并通过IP上TCP的调用参数或结果在TCP /网络接口中传输。 |
16 |
Urgent Pointer | 此字段传达紧急指针的当前值,作为与该段中序列号的正偏移量。紧急指针指向紧随紧急数据之后的八位位组的序号。仅在设置了URG控制位的段中解释此字段。 | 16 |
Options | 选项可能会占用TCP标头末尾的空间,并且是8位长度的倍数。所有选项都包含在校验和中。选项可以在任何八位位组边界上开始。选项的格式有两种情况: | 8的倍数 |
情况1:一个八位组。 | ||
情况2:八位位组,选项长度的八位位组和实际的选项数据八位位组。选项长度计算选项类型和选项长度的两个八位位组以及选项数据八位位组。请注意,选项列表可能比数据偏移量字段暗示的要短。超出选项结尾选项的标头内容必须为标头填充(即零)。 |
TCP通讯
在将TCP用于任何实际有用的目的(即发送数据)之前,必须在希望通信的两个设备之间建立连接。此过程通常称为连接建立,涉及交换消息,该消息将两个设备从其初始连接状态(CLOSED)转换为正常操作状态(ESTABLISHED)。
连接建立功能
建立连接过程实际上会完成几件事,因为它创建了适合于数据交换的连接:
联系和通信: 客户端和服务器相互联系,并通过相互发送消息建立通信。在这一点之前,服务器通常甚至不知道它将与之对话的客户端,因此它在连接建立期间就发现了这一点。
序列号同步: 每个设备都让对方知道其首次传输要使用的初始序列号。
参数交换: 控制TCP连接操作的某些参数由两个设备交换。
用于建立连接的控制消息:SYN和ACK
TCP使用控制消息来管理联系和通信过程。但是,没有任何特殊的TCP控制消息类型。所有TCP消息均使用相同的段格式。TCP报头中的一组控制标志指示段是用于控制目的还是仅用于承载数据。使用控制消息时,以下标志会更改。
SYN: 该位指示该段正在用于初始化连接。参考上面提到的序列号同步,SYN表示同步。
ACK: 此位指示发送网段的设备正在传送对其已接收消息(例如SYN)的确认。
正常连接建立:“三次握手”
为了建立连接,每个设备必须发送一个SYN并从另一个设备接收一个ACK。因此,从概念上讲,需要在设备之间传递四个控制消息。但是,当一个人可以同时通信时,在单独的消息中发送SYN和ACK效率很低。因此,在连接建立中的正常事件序列中,通过设置两个相关位(有时称为SYN + ACK的消息)来一起发送SYN之一和ACK之一。这总共产生了三个消息,因此,连接过程称为三次握手。
关键: 在TCP客户端和服务器之间建立连接的正常过程包括三个步骤:
客户端发送SYN消息
服务器发送结合了客户端SYN的ACK并包含服务器SYN的消息
- 然后客户端发送针对服务器的SYN的ACK。这称为TCP三次握手。
连接在其生存周期内会经历一系列状态,这包括:
状态名称 | 状态含义 |
---|---|
LISTEN | 正在等待来自任何远程TCP和端口的连接请求 |
SYN-SENT | 发送连接请求后等待匹配的连接请求 |
SYN-RECEIVED | 已接收并发送连接请求后,等待确认连接请求确认 |
ESTABLISHED | 一个开放的连接,接收到的数据可以传递给用户。连接的数据传输阶段的正常状态 |
FIN-WAIT-1 | 等待来自远程TCP的连接终止请求,或者等待先前发送的连接终止请求的确认 |
FIN-WAIT-2 | 等待来自远程TCP的连接终止请求 |
CLOSE-WAIT | 正在等待本地用户的连接终止请求 |
CLOSING | 等待来自远程TCP的连接终止请求确认 |
LAST-ACK | 等待先前发送给远程TCP的连接终止请求的确认(包括对它的连接终止请求的确认)。 |
TIME-WAIT | 等待足够的时间以确保远程TCP收到其连接终止请求的确认。 |
CLOSED | 完全没有连接状态。 |
UDP
UDP是一种无连接且不可靠的传输协议,这两个端口用于标识源计算机和目标计算机内的端点。当不需要可靠的传送时,使用用户数据报协议代替TCP。但是,从不使用UDP发送重要数据,例如网页,数据库信息等。流媒体(例如视频,音频等)使用UDP,因为它提供速度。
为什么UDP比TCP快?
UDP比TCP快的原因是因为没有任何形式的流控制。UDP不会进行错误检查,错误纠正或确认。UDP只与速度有关。因此,当Internet上发送的数据受到冲突的影响时,就会出现错误。
UDP数据包称为8字节标头的用户数据报。用户数据报的格式如图3所示。在用户数据报中,前8个字节包含头信息,其余字节包含数据。
UDP数据报
名称 | 含义 |
---|---|
Source port number | 正在传输数据的源主机使用的端口号。它是16位长。因此,端口号的范围是0到65,535。 |
Destination port number | 正在获取数据的目标主机使用的端口号。它也是16位长,并且端口范围的数量与源主机相同。 |
length | 字段是一个16位字段。它包含用户数据报,标头和数据的总长度。 |
Checksum | UDP校验和是可选的。它用于检测数据错误。如果该字段为零,则不计算校验和。然后计算得出的true字段包含1。 |
UDP的特征
UDP的特征如下。
端到端。UDP可以识别计算机上运行的特定进程。
不可靠的无连接传送
UDP使用无连接通信设置。在这种情况下,UDP无需在发送数据之前建立连接。通信仅由数据段本身组成
尽力而为
无应答,无顺序,无流量控制
可能会丢失,重复,延迟,乱序或失去连接
快速,低开销
- 适用于可靠的本地网络
- RTP(实时传输协议)
在通讯中使用端口
接收到数据之后,计算机必须具有某种处理机制。考虑到用户已打开三个应用程序,例如Web浏览器,telnet会话和FTP会话。这三个应用程序都正在通过网络移动数据。因此,应该有某种机制来确定操作系统将哪些流量绑定到哪个应用程序。要处理这种情况,请使用网络端口。可用端口的范围是0到65535。其中0到1023是众所周知的端口 ,1023到49151是注册端口,49152到65535是动态端口。
使用UDP协议的常见端口:
端口 | 服务 |
---|---|
7 | Echo |
9 | Discard |
11 | Users |
13 | Daytime |
17 | Quote |
19 | Chargen |
53 | Nameserver |
67 | Bootps |
68 | Bootpc |
69 | TFTP |
111 | RPC |
123 | NTP |
UDP通信
在UDP连接中,客户端根据他们开始连接的程序设置唯一的源端口号。UDP不限于一对一交互。可以使用广播或多播寻址提供一对多交互。与单台服务器通信的许多客户端可以提供多对一交互。多对多交互只是这些技术的扩展。
TCP vs UDP
UDP | TCP | |
---|---|---|
是否连接 | 无连接 | 面向连接 |
是否可靠 | 不可靠传输,不使用流量控制和拥塞控制 | 可靠传输,使用流量控制和拥塞控制 |
连接对象个数 | 支持一对一,一对多,多对一和多对多交互通信 | 只能是一对一通信 |
传输方式 | 面向报文 | 面向字节流 |
首部开销 | 首部开销小,仅8字节 | 首部最小20字节,最大60字节 |
适用场景 | 适用于实时应用(IP电话、视频会议、直播等) | 适用于要求可靠传输的应用,例如文件传输 |
如何测试一个端口是否通信
telnet
和一些奇奇怪怪的工具我就不说了,如果您认为某些网站上的工具好用,请Alt + F4。
如果是个人电脑,没所谓,用些小工具可以,但是Server的话可不能因为测试就随便装某些奇怪的东西。
在Windows上测试端口
telnet
不是本文关注内容
Test-NetConnection
这是PowerShell提供的能力,支持ping
,TCP
,traceroute
ping测试:
1
Test-NetConnection -ComputerName www.hit.edu.cn -InformationLevel Detailed
路由测试(管理员权限运行):
1
Test-NetConnection -ComputerName www.hit.edu.cn -DiagnoseRouting -InformationLevel Detailed
TCP端口连通性测试:
1
Test-NetConnection -ComputerName www.hit.edu.cn -Port 80 -InformationLevel Detailed
Trace测试:
1
Test-NetConnection -ComputerName www.hit.edu.cn -TraceRoute
InformationLevel Detailed
参数可选。
在Linux/Unix上测试端口
telnet仍不不关注
netcat
需要使用包管理(apt/yum等)安装nc(netcat):
1 | yum -y install nc |
比如咱们测试192.168.1.1的TCP22端口:
1 | nc -vz 192.168.1.1 22 |
如果可以连通,会在标准输出回显successded
。
nmap
nmap
其实是一个网络扫描工具,但是也可以使用,首先也是安装nmap包,省略步骤,然后咱们继续测试22,
1 | nmap -sT -v -p 22 192.168.1.1 |
具体参数需要养成查阅man
手册的好习惯。
UDP端口测试
这才是写这个文档的目的,这个问题困扰很多人,如果有人问你如何测试一个UDP端口是否可达?
其实这个问题就是个错误(虽然某些方式可以验证是否可达),先说为什么,再说怎么做。
其实没有所谓的开放UDP端口,大多数人惯于思考的意义上(这是在回答,确认,我以接受连接,这一类意思)。UDP是无会话的,因此,所谓Port
(读取:OS中IP协议栈中的UDP协议)将永远不会自行响应,也就是所谓的三次握手完成后,所响应的成功。(后面会说各种工具对于UDP端口的测试是如何实现的)
UDP端口有两种状态:监听与未监听。其实也就是某些进程是否打开套接字。后一种(未打开套接字)情况比较容易检测,因为系统使用`code=3(端口不可达)ICMP Destination Unrechable进行响应。但是,许多防火墙会丢弃这种数据包,因此如果没有得到任何回应,就不能确切知道端口是否处于这种状态。(ICMP也是无会话的,并不会重传),这句话是什么意思呢,就是ICMP Destination Unrechable代表的端口不可达数据包很有可能在途中某个地方被丢弃或丢失。
处于监听状态的UDP
端口也可能根本不响应(正在监听它的进程只是接收数据包,并不传输任何内容),或者将某些内容发送回去。也就是说,如果什么也拿不回来,永远无法确定此端口的状态是什么。
有些啰嗦,说的是啥意思呢,就是不通不代表不通,也没有会话控制,无需重传。
那么测试的办法又是什么呢,像nc,nmap这些工具是如何判断UDP端口是否可达呢?
咱们试验一下:
实验用到的工具: nc
、tcpdump/wireshark
、nmap
。
首先,模拟一个监听的UDP端口,并使用tcpdump
或wireshark
抓包,另一个客户端请求这个端口。
服务端使用
netcat
监听udp端口6666:1
nc -ul 6666 # 监听udp6666端口
服务端抓包:
1
tcpdump -i enp0s31f6 udp port 6666 -X
防火墙先不开通udp6666:
现在客户端可以使用nc或nmap测试端口了:
1 | nc -uv SERVER_IP 6666 |
Connection to 192.168.1.182 6777 port [udp/*] succeeded!
这时可以键入字符,看server端是否接受到对应输入的字符;
抓包同时查看,
具体不贴图了,多个电脑倒来倒去麻烦,其实目的就是看下
测试结果
其实UDP端口测试,如无外接因素影响的话,nc nmap都可以简单的检测,不过,如果主机防火墙或链路中存在防火墙,这就不确定了。所以下次,如果有人问你如何测试UDP端口,请送上一枚斜眼币。
基于UDP的可靠传输协议
TCP/IP协议栈中,TCP和UDP属于传输层,负责实现数据的传输。其中TCP是面向连接的和基于单个字节流的、保证顺序的可靠传输协议,UDP是无连接的、不可靠的、面向报文的协议。
在实际应用中,TCP由于简单可靠,被大部分应用层协议使用,特别是HTTP,所以占据了互联网流量的主要部分。由于TCP的广泛应用,并且是实现在操作系统中,在参数和算法调整上比较受限,难以进行一些激进的改进和定制。另外TCP的NAT穿越比较困难,一些P2P应用也只能使用UDP,所以就有了各种各样的可靠UDP协议。
可靠UDP协议
UDT(UDP-based Data Transfer Protocol)
UDT的主要目的是支持高速广域网上的海量数据传输,所以除了在UDP之上实现类似TCP的协议和算法之外,UDT还对TCP的拥塞算法做了一些细节上的调整,包括Negative-ACK(NAK)、ACK to ACK(ACK2)、基于对数的动态AIMD等。不过UDT的重传效率较低,无效报文,实际效果并不理想。
KCP
KCP是一个很简单的ARQ的实现,包括选择重传和快重传等机制,对上层提供一个可靠的字节流。应用层可以使用多流复用的框架来实现对多个流的支持。另外,KCP增加了可配置启用的加密和FEC选项,FEC用的是Reed-Solomon纠删码,例如可以配置发送10%的冗余数据,来减少丢包时需要的重传,从而降低数据传输的延时。
QUIC
QUIC是Google实现的一种可靠UDP传输协议,并且已经被选择作为HTTP/3的基础。它的特点有:
- 内建安全性,集成TLS
- 连接建立过程和TLS协商过程合并,减少往返请求次数,提高连接速度
- 集成多种拥塞算法,包括最新的BBR
- 多流支持,每个流有独立的拥塞控制,避免单个流中的丢包阻塞其它所有流(Head-of-line Blocking问题),更好的支持类似HTTP/2中的乱序请求
- 连接迁移:QUIC可以通过连接ID来唯一标识一个连接,当用户在有线、无线、移动网络之间切换时,可以保持上层连接的有效性,不需要再进行重连。
另外,早期的QUIC还使用了一种基于异或的FEC算法,不过在新版本中已经去掉。
uTP
uTP是BitTorrent中新增加的一种UDP传输协议,主要特点是使用了LEDBAT(Low Extra Delay Background Transport)拥塞算法。这种算法基于延时来检测网络拥塞,可以更早的探测到拥塞和更早的以及更大幅度的进行避让,从而避免影响用户上网操作的进行,保持后台下载跟前台操作的和平共处。
FASP(Aspera)
FASP是Aspera公司(已被IBM收购)的私有UDP解决方案,提供加密的可靠传输,拥塞算法估计是类似BBR,直接使用RTT和带宽来作为调节速度的参考。但FASP主要用于高速的文件传输,所以不需要保证报文的顺序,避免乱序重组时占用的内存开销,而且也避免了因为内存有限而丢弃的部分乱序报文,从而减少不必要的重传,提高传输速度。也就是说,完全避免了Head-of-line Blocking问题。
SCTP(Stream Control Transmission Protocol,流控制传输协议)
准确的说,SCTP不是一种可靠UDP协议,而是一种跟TCP/UDP平级的传输层协议,是IETF在2000年指定的标准协议。目前Linux和部分UNIX已经集成,Windows和Mac需要使用第三方包来实现。SCTP最初主要用于电信系统,此外,WebRTC中的DataChannel也用到这个协议。它的特点有:
- 跟TCP一样面向连接,提供可靠传输
- 跟UDP一样面向消息
- 多流支持
- 每个流可以配置成接受有序或无序的消息
- Multi-Homing:可以配置多个地址,利用多条网络传输通道
- 更好的安全性:要求四次握手,避免TCP的SYN Flooding攻击