《tcp&udp报文格式》由会员分享,可在线阅读,更多相关《tcp&udp报文格式(10页珍藏版)》请在金锄头文库上搜索。
1、TCP/UDP 报文格式 TCP 协议为终端设备提供了面向连接的、可靠的网络服务,UDP 协议为终端设备提供了无连接的、不可靠的数据报服务。从上图我们可以看出,TCP 协议为了保证数据传输的可靠性,相对于 UDP 报文,TCP 报文头部有更多的字段选项。首先让我们来看一下 TCP 的报文头部主要字段:每个 TCP 报文头部都包含源端口号(source port)和目的端口号(destination port),用于标识和区分源端设备和目的端设备的应用进程。在 TCP/IP 协议栈中,源端口号和目的端口号分别与源 IP 地址和目的 IP 地址组成套接字( socket),唯一的确定一条 TCP
2、连接。序列号(Sequence number)字段用来标识 TCP 源端设备向目的端设备发送的字节流,它表示在这个报文段中的第一个数据字节。如果将字节流看作在两个应用程序间的单向流动,则 TCP 用序列号对每个字节进行计数。序列号是一个 32bits 的数。既然每个传输的字节都被计数,确认序号(Acknowledgement number,32bits )包含发送确认的一端所期望接收到的下一个序号。因此,确认序号应该是上次已成功收到的数据字节序列号加 1。TCP 的流量控制由连接的每一端通过声明的窗口大小(windows size)来提供。窗口大小用数据包来表示,例如 Windows size
3、=3, 表示一次可以发送三个数据包。窗口大小起始于确认字段指明的值,是一个 16bits 字段。窗口大小可以调节。 校验和(checksum)字段用于校验 TCP 报头部分和数据部分的正确性。最常见的可选字段是 MSS(Maximum Segment Size,最大报文大小)。MSS 指明本端所能够接收的最大长度的报文段。当一个 TCP 连接建立时,连接的双方都要通告各自的 MSS 协商可以传输的最大报文长度。我们常见的 MSS 有 1024(以太网可达 1460 字节)字节。相对于 TCP 报文,UDP 报文只有少量的字段:源端口号、目的端口号、长度、校验和等,各个字段功能和 TCP 报文相
4、应字段一样。UDP 报文没有可靠性保证和顺序保证字段,流量控制字段等,可靠性较差。当然,使用传输层 UDP 服务的应用程序也有优势。正因为 UDP 协议较少的控制选项,在数据传输过程中,延迟较小,数据传输效率较高,适合于对可靠性要求并不高的应用程序,或者可以保障可靠性的应用程序像 DNS、TFTP、SNMP 等;UDP 协议也可以用于传输链路可靠的网络。UDP 报文UDP 报头定长为 8B。按顺序为:1,UInt16 源端口号关于端口号有一些规定,服务器端通常用熟知端口号,通常在 0-1023 之间。而客户端用随机的端口号,其范围在 49152 到 65535 之间。2,UInt16 目的端口
5、号3,UInt16 总长度包括报头和数据的长度之和。显然在8,65535区间。4,UInt16 检验和如果不需要检验和,就取 0。如果需要检验和,那么其算法为:(1)构造 12B 的伪报头UInt32 源 IP+UInt32 目的 IP+Byte 0+Byte 17+UInt16 总长度(上面所说的)(2)UDP 的报头(3)UDP 的数据部分unsafe UInt16 计算校验和(UInt16* buffer, int size)Int32 cksum = 0;int counter;counter = 0;while (size 0)UInt16 val = buffercounter;c
6、ksum += Convert.ToInt32(buffercounter);counter += 1;size -= 1;cksum = (cksum 16) + (cksum cksum += (cksum 16);return (UInt16)(cksum);构造 UDP 报文(含有检验和)需要的输入参数包括:UInt32 源 IP、UInt32 目的 IP、UInt16 源端口号、UInt16 目的端口号、Byte 数据部分、Uint16 数据部分的长度public Byte 构造 UDP 数据报(UInt32 源 IP, UInt32 目的 IP, UInt16 源端口号, UInt
7、16 目的端口号, Byte 数据部分, UInt16 数据部分的长度) UInt16 总长度 = (UInt16)(8 + 数据部分的长度);UInt16 校验和 = 0;/网络字节顺序源 IP=(uint)IPAddress.HostToNetworkOrder(int)源 IP);目的 IP = (uint)IPAddress.HostToNetworkOrder(int)目的 IP);源端口号 = (ushort)IPAddress.HostToNetworkOrder(Int16)源端口号);目的端口号 = (ushort)IPAddress.HostToNetworkOrder(I
8、nt16)目的端口号);总长度 = (ushort)IPAddress.HostToNetworkOrder(Int16)总长度);/Byte udpbytes = new Byte8 + 数据部分的长度;BitConverter.GetBytes(源端口号).CopyTo(udpbytes, 0);/填入源端口号BitConverter.GetBytes(目的端口号).CopyTo(udpbytes, 2);/填入目的端口号BitConverter.GetBytes(总长度).CopyTo(udpbytes, 4);/填入总长度BitConverter.GetBytes(校验和).CopyT
9、o(udpbytes, 6);/校验和数据部分.CopyTo(udpbytes, 8);/下面是计算校验和.数据部分如果不是偶数字节则补一个字节.byte 伪报文 = new byte20 + (数据部分的长度+1) / 2*2;/确保偶数字节BitConverter.GetBytes(源 IP).CopyTo(伪报文, 0);/填入源端口号BitConverter.GetBytes(目的 IP).CopyTo(伪报文, 4);/填入目的端口号伪报文8 =0;/ 填充 0.网络字节顺序伪报文9 = 17;/和 UDP 协议号 BitConverter.GetBytes(总长度).CopyTo(
10、 伪报文, 10);/ 填入总长度udpbytes.CopyTo(伪报文, 12);/string ss = 网络字节串(伪报文 );unsafefixed (byte * pt = 伪报文)ushort* pu = (ushort*)pt;校验和 = 计算校验和(pu, 伪报文.Length/2);/不知道为什么不对校验和进行网络字节顺序的调整BitConverter.GetBytes(校验和).CopyTo(udpbytes, 6);/校验和return udpbytes;TCP UDP 报文解析1 UDP 报文:UDP 报文比较简单,由四个字段组成,每个字段 2 个字节:(1) 源端口
11、source port(2) 目的端口 destination port(3) 长度 :UDP 用户数据报的长度(4) 检验和 checksumscapy 中定义的 UDP 类(参数一一对应) ls(UDP)sport : ShortEnumField = (53)dport : ShortEnumField = (53)len : ShortField = (None)chksum : XShortField = (None)我们用这个发一个完整的 UDP 数据包。定义: eth=Ether() ip=IP(dst=10.104.4.13) udp=UDP(sport=4321,dport=
12、4321) udpPacket=eth/ip/udp/This is an UDP datagram sendp(udpPacket).Sent 1 packets. udpPacket.show()# Ethernet #dst= 00:11:85:ae:03:3bsrc= 00:22:15:27:69:16 type= 0x800# IP #version= 4ihl= Nonetos= 0x0len= Noneid= 1flags=frag= 0ttl= 64proto= udpchksum= 0x0src= 10.104.4.23dst= 10.104.4.13options= # U
13、DP #sport= 4321dport= 4321len= Nonechksum= 0x0# Raw #load= This is an UDP datagram成功发送,而且我们发现一些参数是默认填充和计算的。 len(udpPacket)65UDP 中的 UDP 用户数据报长度是 31,正好是总长度 65-20(IP 头)-14(ethernet 头)31这个 checksum 长度就是 UDP 头(8 字节固定)后面的 Data 长度2 TCP 报文:TCP 首部比较复杂,分为两大部分,前 20 个字节是大小固定的,后面的选项部分大小不固定。首部固定部分各段意义:(1) 源端口 sou
14、rce port 2 个字节(2) 目的端口 destination port 2 个字节(3) 序号:sequence number,TCP 传送的是面向连接的连续的数据流,所传送的数据每一个字节都编上一个序号,首部的这个序号指的是本报文段所发送的数据的第一个字节的序号,占 4 个字节(4) 确认号:Ack number,是期望受到对方的下一个报文段的数据的第一个字节的序号,也就是期望收到的下一个报文段首部的序号字段的值,占 4 个字节(5)数据偏移:占 4 位,(单位是 4 字节),类似于 IP 包头的首部长度,他是指 TCP 报文段首部的长度,由于存在长度不确定的选项字段,所以此值最小为
15、 20 字节,最大为 60 字节(6)保留:6bit,目前没用,设为 0(7)这里的 6 位是说明本报文段性质的,下面再详细说(8)窗口:window,占 2 个字节,用来控制对方发送的数量(9)检验和:checksum,2 个字节,检验范围为首部加数据两部分下面看看那 6 位的控制部分各位的含义:SYN:该标志位用来建立连接,让连接双方同步序列号.FIN:表示发送端已经没有数据要求传输了,希望释放连接.RST:用来复位一个连接.RST 标志置位的数据包称为复位包.一般情况下,如果 TCP 收到的一个分段明显不是属于该主机上的任何一个连接,则向远程发送一个复位包.URG:为紧急数据标志.如果他为 1,表示本数据包中包含紧急数据.此时紧急数据指针有效.ACK:为确认标志位.如果为 1,表示包中的确认号时有效的.否则,包中的确认号无效.PSH:如果置位,接收端应尽快把数据传诵给应用层.看个实际抓的一个包: 前面 2 位是保留,第三位是 URG,第四位是 ACK,第五位是 PSH,第六位是 RST,第七位是SYN,第八位是 FIN。可变部分就是选项和填充:长度可变。 ls(TCP)sport : ShortEnumField = (20) 2 字节源