JavaSocket编程前奏之TCP与UDP报文解析

TCP是Transmission Control Protocol 传输控制协议的简称,是一种面向连接的、可靠的、基于字节流的传输层网络通信协议。TCP/IP只是一个协议栈,Socket是TCP/IP协议的一个非常优秀的编程接口,两个应用程序通过一个双向的通信连接实现数据的交换,双向通信链路的一端就称为一个Socket,链路的两端分别称为客户端Client和服务端Server。

1.TCP与UDP的区别

TCP传输控制协议,是一种提供可靠数据传输的通用协议,传输双方需要事先建立可靠的连接,提供高可靠性服务。UDP用户数据报协议,是一个面向无连接的协议,通信双方不需要先建立连接,UDP协议不提供差错恢复,不能提供数据重传,因此该协议传输数据安全性差,提供高效率的服务。
下表详细对比TCP和UDP之间的区别

JavaSocket编程前奏之TCP与UDP报文解析_第1张图片
TCP和UDP之间的区别


2.TCP与UDP的报文格式

TCP报文格式:
一个TCP报文的头部是20个字节。TCP报文段首部格式如下图

JavaSocket编程前奏之TCP与UDP报文解析_第2张图片
TCP报文格式

源端口(SourcePort),目标端口(DestinationPort)各2字节:
源端口号,标识主机上发起传送的应用程序;目的端口标识主机上传送要到达的应用程序。源端和目的端的端口号,用于寻找发端和收端应用进程。

封包序号(SequenceNumber) 4字节:
TCP报文太大时需要分段,Sequence Number 就是记录每个封包的序号。序号字段的值则指的是本报文段所发送的数据的第一个字节的序号。

确认号(AcknowledgeNumber)4字节:
当 client 端收到确认码时,就确定之前传递的封包已经被正确的收下。这个确认号是期望收到对方的下一个报文段的数据的第一个字节的序号。

数据偏移(DataOffset)4比特:
TCP报文段的数据起始处距离TCP报文段的起始处有多远。“数据偏移”的单位不是字节而是32bit字(4字节为计算单位)

保留字段(Reserved)占6比特:
保留为保留使用,但目前应置为0。

状态控制码(Code,Control Flag):
标志位字段(U、A、P、R、S、F):占6比特。
URG:紧急比特(urgent),当URG=1时,表明紧急指针字段有效,代表该封包为紧急封包。
ACK:确认比特(Acknowledge)。只有当ACK=1时确认号字段才有效,代表这个封包为确认封包。当ACK=0时,确认号无效。
PSH:(Push function)若为1时,代表要求对方立即传送缓冲区内的其他对应封包,而无需等缓冲满了才送。
RST:复位比特(Reset) ,当RST=1时,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立传输连接。
SYN:同步比特(Synchronous),SYN置为1,就表示这是一个连接请求或连接接受报文,通常带有 SYN 标志的封包表示『主动』要连接到对方的意思。
FIN:终止比特(Final),用来释放一个连接。当FIN=1时,表明此报文段的发送端的数据已发送完毕,并要求释放运输连接。

滑动窗口(Window)占2字节
窗口字段用来控制对方发送的数据量,可以告知对方目前本身有的缓冲器容量(Receive Buffer) 还可以接收封包。当 Window=0时,代表缓冲器已经满额,应该暂停传输数据。单位为字节。

TCP校验和(Checksum) 占2字节
当数据要由发送端送出前,会进行一个检验的动作,并将该动作的检验值标注在这个字段上;而接收者收到这个封包之后,会再次的对封包进行验证,并且比对原发送的 Checksum 值是否相符,如果相符就接受,若不符就会假设该封包已经损毁,进而要求对方重新发送此封包!在计算检验和时,要在TCP报文段的前面加上12字节的伪首部。

紧急指针(UrgentPointer) 占2字节
这个字段是在 Code 字段内的 URG = 1 时才会产生作用。

选项(Options)长度可变。
TCP首部可以有多达40字节的可选信息,用于把附加信息传递给终点,或用来对齐其它选项。TCP首部的主要选项:最大报文段长度MSS(Maximum Segment Size)是TCP报文段中的数据字段的最大长度。

填充字段(Padding)
如同 IP 封包需要有固定的 32bits 表头一样, Options 由于字段为非固定,所以也需要 Padding 字段来加以补齐才行。同样也是 32 bits 的整数倍。这是为了使整个首部长度是4字节的整数倍。

UDP报文格式:
一个UDP报文分为数据部分和头部,最小是8个字节(仅有头部)。UDP报文格式如下图:

JavaSocket编程前奏之TCP与UDP报文解析_第3张图片
UDP报文格式

伪首部(12字节):不是报文的真正首部,只是为了及时校验和才引入的,伪首部包括4个字节的源IP地址,4个字节的目的IP地址,1个字节的0,1个字节的数字17,2个字节的UDP长度。
UDP检验和:把首部和数据一起进行校验。接收端进行的校验和与UDP报文中的校验和相与,如果无差错应该全为1。如果有误,则将报文丢弃或者发给应用层、并附上差错警告。
UDP检验和计算方式如下图

JavaSocket编程前奏之TCP与UDP报文解析_第4张图片
UDP检验和计算方式


3.TCP建立连接3次握手和断开连接4次挥手

JavaSocket编程前奏之TCP与UDP报文解析_第5张图片
TCP建立连接3次握手和断开连接4次挥手

TCP建立连接三次握手过程

a) Client通过向Server发送一个含有同步序列号的标志位的数据段给Server ,将标志位SYN置1,随机产生一个值seq=x向Server请求建立连接,通过这个数据段,
b) Client进入SYN_SENT状态,等待Server确认。Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ACK=x+1,随机产生一个值seq=y,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
c) Client收到确认后,检查ACK是否为x+1,ACK是否为1,如果正确则将标志位ACK置为1,ACK=y+1,并将该数据包发送给Server,Server检查ACK是否为y+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。

TCP断开连接的四次挥手过程

由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到另一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。
a) Client发送一个FIN,数据传输的顺序seq=x+2,ACK=y+1用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
b) Server收到FIN后,发送一个ACK给Client,确认序号为ACK=x+3即收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
c) Server发送一个FIN,随机数seq=y+1,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
d) Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为ACK=y+2即收到序号+1,Server进入CLOSED状态,完成四次挥手。

本订阅号提供Java相关技术分享,从Java编程基础到Java高级技术,从JavaWeb技术基础Jsp、Servlet、>JDBC到SSH、SSM开发框架,从REST风格接口设计到分布式项目实战。剖析主流开源技术框架,用亲身
实践来谱写深度Java技术日志。

JavaSocket编程前奏之TCP与UDP报文解析_第6张图片
Java技术日志

欢迎关注 Java技术日志 微信订阅号

你可能感兴趣的:(JavaSocket编程前奏之TCP与UDP报文解析)