一、TCPIP4数据结构
struct TCP_IPv4_Packet_Type
{
u8 dest_MAC[6]; //存放目的MAC地址
u8 src_MAC[6]; //存放源MAC地址
u8 type[2];
//太网帧的类型
//0x0800表示后面跟着的是IPV4数据包;
//0x0806表示后面跟着的是ARP数据包;
//0x86dd表示后面跟着的是IPV6数据包;
///IP头部/IPV4头部(IPv4 header),占20个字节///
u8 vhl;
//IP版本和IP头部长度:
//版本(Version):0x45 的高4位为0x04表示IPv4版本
//头部长度(Header Length):低4位为0x05,表示IPv4头部长度,单位为32位字
//即IP头部/IPV4头部为:5 * 4 = 20 字节。
u8 tos; //服务类型
u8 len[2]; //IP报文总长度2个字节,它是"IP头,TCP头部和TCP数据的长度"
u8 ipid[2];
//TCP数据包ID,2字节,表示数据包唯一ID,分片时,所有分片段使用相同ID,表示属于同一包数据。
//是"发送方"采用"ID计数器"得到的数值
u8 ipoffset[2];
//标志字段和片偏移字段
//标志字段第1位(保留位,bit15)始终为0;
//标志字段第2位(DF位,bit14),DF=1禁止对该数据包分片;DF=0允许分片;
//标志字段第3位(MF位,bit13),MF=1表示后续还有分片;MF=0表示当前是最后一个分片;
//片偏移字段占13位,bit12:0,表示"当前分片"在原始数据包中的起始位置。
//计算方式:偏移值 = 起始字节数 / 8。如果偏移值为5,则表示分片在原始数据包中,是从第5*8=40字节开始。
//0x40 0x00, 禁止对该数据包分片。
//DF=0允许分片,但MF=0表示当前是最后一个分片,也就是没有分片。
u8 ttl; //数据包生存时间
u8 protocol; //协议:1字节,如6表示TCP,17表示UDP
u8 ipchksum[2]; //检验和
u8 Send_IP[4];//发送方IP地址,4字节
u8 Receive_IP[4];//接收方IP地址,4字节
////TCP头部(TCP header)总共为20字节////
//但是,在某些场合,特别是在处理选项(Options)时,TCP头部的长度为24字节。
u8 Send_Port[2]; //发送方端口,0x06 0x10,表示发送方端口为1552
u8 Receive_Port[2]; //接收方端口,0x13 0x88,表示接收方端口:5000
u8 seqno[4]; //序列号,比如:0x4B 0xF8 0x27 0x37
u8 ackno[4]; //确认号,比如:0x00 0x00 0x00 0x00
u8 tcpoffset;//表示TCP头部的长度,即(0x70>>4)*4=28;
u8 flags;
//TCP标志位定义如下:
#define TCP_FIN 0x01
//bit0终止标志,表示关闭连接。如果发送带有"FIN标志位的TCP数据包",则连接将被断开
#define TCP_SYN 0x02
//bit1为同步请求标志,表示这是一个同步请求:如果客户端发送SYN包,则服务器响应SYN-ACK包,然后客户端发送ACK确认包。
#define TCP_RST 0x04
//bit2为复位标志,当发送RST包后,发送方会立即关闭连接,而不需要等待对方的确认。接收方收到RST包后,也会立即关闭连接。
#define TCP_PSH 0x08
//bit3推送标志,表示推送。push操作是指将"数据包"立即发送给应用程序,而不是在缓冲区中排队。
#define TCP_ACK 0x10 //bit4确认标志,表示响应。
#define TCP_URG 0x20 //bit5紧急标志,表示紧急指针。
#define TCP_CTL 0x3f
u8 wnd[2];
//窗口大小, 对于发送方来说告诉接收方,当前"发送方接收的缓冲区"的大小
u8 tcpchksum[2]; //校验和
u8 urgp[2]; //紧急指针
u8 optdata[4];
//optdata[0]为"最大段大小"占用的字节数
//optdata[1]为TCP选项中MSS选项的长度
//MSS选项的长度占1个字节,最大段高8数值,最大段低8数值
};
二、TCP序列号和确认号
TCP的每个数据包中都含有一个序列号和一个确认号。这就保证了传送数据包的顺序。
在TCP通讯中,主要有建立连接、传输数据、关闭连接三个过程。每个过程的序列号和确认号的变化也是不同的。
1、建立连接
TCP建立连接,需要进行三次握手,也就是需要3步才能建立连接。
第1步,客户端发送"SYN同步数据包"。
客户端向服务器发送一个"SYN同步数据包",请求建立连接,该数据包中,"初始序列号"是由客户端随机产生的一个值,确认号是0;
发送"SYN同步数据包":
0xB4 0x2E 0x99 0x59 0xEC 0x1E 0x00 0x08 0xDC 0x11 0x11 0x02 0x08 0x00
0x45 0x00 0x00 0x2C 0x00 0x01 0x00 0x00 0x40 0x06 0xF6 0xAB 0xC0 0xA8 0x01 0x11 0xC0 0xA8 0x01 0xBE
0x03 0xE8 0x13 0x88 0x00 0x00 0xA0 0xB1 0x00 0x00 0x00 0x00 0x60 0x02 0x05 0xB4 0x56 0x31 0x00 0x00 0x02 0x04 0x05 0xB4
分析得到序列号为"0x00 0x00 0xA0 0xB1",客户端的初始序列号是一个随机数。
分析得到确认号为"0x00 0x00 0x00 0x00",默认为0
第2步,客户端接收"SYN+ACK数据包"。
服务器收到"SYN同步数据包"后,会对客户端进行一次同步确认。因此,这个数据包中,"初始序列号"是由服务器随机产生的一个值,
确认号是"客户端的初始序列号+1";
接收来自服务端的"SYN+ACK数据包":
0x00 0x08 0xDC 0x11 0x11 0x02 0xB4 0x2E 0x99 0x59 0xEC 0x1E 0x08 0x00
0x45 0x00 0x00 0x2C 0x42 0x89 0x40 0x00 0x80 0x06 0x34 0x23 0xC0 0xA8 0x01 0xBE 0xC0 0xA8 0x01 0x11
0x13 0x88 0x03 0xE8 0x60 0xC5 0xE0 0x71 0x00 0x00 0xA0 0xB2 0x60 0x12 0xFA 0xF0 0x1F 0xAC 0x00 0x00 0x02 0x04 0x05 0xB4 0x00 0x00
分析得到序列号为"0x60 0xC5 0xE0 0x71",服务端的初始序列号是一个随机数。
分析得到确认号为"0x00 0x00 0xA0 0xB2",它是"客户端的初始序列号+1"
第3步,客户端发送"ACK数据包"。
客户端客户端收到"SYN+ACK数据包"后,还要对服务器进行一次确认。该数据包中,序列号是"SYN同步数据包"中的"确认号",
而"确认号"是"服务端的初始序列号+1"。
发送"ACK数据包":
0xB4 0x2E 0x99 0x59 0xEC 0x1E 0x00 0x08 0xDC 0x11 0x11 0x02 0x08 0x00
0x45 0x00 0x00 0x28 0x00 0x02 0x00 0x00 0x40 0x06 0xF6 0xAE 0xC0 0xA8 0x01 0x11 0xC0 0xA8 0x01 0xBE
0x03 0xE8 0x13 0x88 0x00 0x00 0xA0 0xB2 0x60 0xC5 0xE0 0x72 0x50 0x10 0x05 0xB4 0x2C 0xA6 0x00 0x00
分析得到序列号为"0x00 0x00 0xA0 0xB2",是上次服务端发送的确认号。
分析得到确认号为"0x60 0xC5 0xE0 0x72",是"服务端的初始序列号+1"。
2、传输数据
在TCP建立连接后,就可以开始传输数据了。TCP工作在全双工模式,它可以同时进行双向数据传输。
客户端第1次发送"PSH+ACK数据包",该数据包中的"序列号和确认号"与建立连接的第3步中的数据包中的序列号和确认号是相同的;
1)、客户端发送"PSH+ACK数据包",用户数据内容为ABC
0xB4 0x2E 0x99 0x59 0xEC 0x1E 0x00 0x08 0xDC 0x11 0x11 0x02 0x08 0x00
0x45 0x00 0x00 0x2B 0x00 0x03 0x00 0x00 0x40 0x06 0xF6 0xAA 0xC0 0xA8 0x01 0x11 0xC0 0xA8 0x01 0xBE
0x03 0xE8 0x13 0x88 0x00 0x00 0xA0 0xB2 0x60 0xC5 0xE0 0x72 0x50 0x18 0x05 0xB4 0xA8 0x58 0x00 0x00
ABC
分析得到序列号为"0x00 0x00 0xA0 0xB2",是上次服务端发送的确认号。
分析得到确认号为"0x60 0xC5 0xE0 0x72",是"服务端的初始序列号+1"。
实测,确实如此。
2)、客户端接收"ACK数据包"
0x00 0x08 0xDC 0x11 0x11 0x02 0xB4 0x2E 0x99 0x59 0xEC 0x1E 0x08 0x00
0x45 0x00 0x00 0x28 0x42 0x8A 0x40 0x00 0x80 0x06 0x34 0x26 0xC0 0xA8 0x01 0xBE 0xC0 0xA8 0x01 0x11
0x13 0x88 0x03 0xE8 0x60 0xC5 0xE0 0x72 0x00 0x00 0xA0 0xB50x50 0x10 0xFA 0xED 0x37 0x69 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00
分析得到序列号为"0x60 0xC5 0xE0 0x72",是"服务端的初始序列号+1"。
分析得到确认号为"0x00 0x00 0xA0 0xB5",是上次客户端发送的序列号+3,这个3表示"ABC"数据串的长度。
3)、客户端发送"PSH+ACK数据包",用户数据内容为EFG
0xB4 0x2E 0x99 0x59 0xEC 0x1E 0x00 0x08 0xDC 0x11 0x11 0x02 0x08 0x00
0x45 0x00 0x00 0x2B 0x00 0x04 0x00 0x00 0x40 0x06 0xF6 0xA9 0xC0 0xA8 0x01 0x11 0xC0 0xA8 0x01 0xBE
0x03 0xE8 0x13 0x88 0x00 0x00 0xA0 0xB5 0x60 0xC5 0xE0 0x720x50 0x18 0x05 0xB4 0xA0 0x51 0x00 0x00
EFG
分析得到序列号为"0x00 0x00 0xA0 0xB5"
分析得到确认号为"0x60 0xC5 0xE0 0x72"
4)、客户端接收"ACK数据包"
0x00 0x08 0xDC 0x11 0x11 0x02 0xB4 0x2E 0x99 0x59 0xEC 0x1E 0x08 0x00
0x45 0x00 0x00 0x28 0x42 0x8B 0x40 0x00 0x80 0x06 0x34 0x25 0xC0 0xA8 0x01 0xBE 0xC0 0xA8 0x01 0x11
0x13 0x88 0x03 0xE8 0x60 0xC5 0xE0 0x72 0x00 0x00 0xA0 0xB8 0x50 0x10 0xFA 0xEA 0x37 0x69 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00
分析得到序列号为"0x60 0xC5 0xE0 0x72"
分析得到确认号为"0x00 0x00 0xA0 0xB8"
3、关闭连接
关闭连接的4个步骤如下:
1)、客户端发送"FIN+ACK终止数据包"
0xB4 0x2E 0x99 0x59 0xEC 0x1E 0x00 0x08 0xDC 0x11 0x11 0x02 0x08 0x00
0x45 0x00 0x00 0x28 0x00 0x05 0x00 0x00 0x40 0x06 0xF6 0xAB 0xC0 0xA8 0x01 0x11 0xC0 0xA8 0x01 0xBE
0x03 0xE8 0x13 0x88 0x00 0x00 0xA0 0xB8 0x60 0xC5 0xE0 0x72 0x50 0x11 0x05 0xB4 0x2C 0x9F 0x00 0x00
分析得到序列号为"0x00 0x00 0xA0 0xB8"
分析得到确认号为"0x60 0xC5 0xE0 0x72"
2)、客户端接收"ACK应答数据包"
0x00 0x08 0xDC 0x11 0x11 0x02 0xB4 0x2E 0x99 0x59 0xEC 0x1E 0x08 0x00
0x45 0x00 0x00 0x28 0x42 0x8C 0x40 0x00 0x80 0x06 0x34 0x24 0xC0 0xA8 0x01 0xBE 0xC0 0xA8 0x01 0x11
0x13 0x88 0x03 0xE8 0x60 0xC5 0xE0 0x72 0x00 0x00 0xA0 0xB9 0x50 0x10 0xFA 0xEA 0x37 0x68 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00
分析得到序列号为"0x60 0xC5 0xE0 0x72"
分析得到确认号为"0x00 0x00 0xA0 0xB9"
3)、客户端接收"FIN+ACK终止数据包"
0x00 0x08 0xDC 0x11 0x11 0x02 0xB4 0x2E 0x99 0x59 0xEC 0x1E 0x08 0x00
0x45 0x00 0x00 0x28 0x42 0x8D 0x40 0x00 0x80 0x06 0x34 0x23 0xC0 0xA8 0x01 0xBE 0xC0 0xA8 0x01 0x11
0x13 0x88 0x03 0xE8 0x60 0xC5 0xE0 0x72 0x00 0x00 0xA0 0xB9 0x50 0x11 0xFA 0xEA 0x37 0x67 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00
分析得到序列号为"0x60 0xC5 0xE0 0x72"
分析得到确认号为"0x00 0x00 0xA0 0xB9
4)、客户端发送"ACK应答数据包"
0xB4 0x2E 0x99 0x59 0xEC 0x1E 0x00 0x08 0xDC 0x11 0x11 0x02 0x08 0x00
0x45 0x00 0x00 0x28 0x00 0x06 0x00 0x00 0x40 0x06 0xF6 0xAA 0xC0 0xA8 0x01 0x11 0xC0 0xA8 0x01 0xBE
0x03 0xE8 0x13 0x88 0x00 0x00 0xA0 0xB9 0x60 0xC5 0xE0 0x73 0x50 0x10 0x05 0xB4 0x3C 0x9E 0x00 0x00
分析得到序列号为"0x00 0x00 0xA0 0xB9"
分析得到确认号为"0x60 0xC5 0xE0 0x73"
4、RST数据包
0xB4 0x2E 0x99 0x59 0xEC 0x1E 0x00 0x08 0xDC 0x11 0x11 0x02 0x08 0x00
0x45 0x00 0x00 0x28 0x00 0x05 0x00 0x00 0x40 0x06 0xF6 0xAB 0xC0 0xA8 0x01 0x11 0xC0 0xA8 0x01 0xBE
0x03 0xE8 0x13 0x88 0x00 0x00 0xA0 0xB8 0x19 0x2C 0x84 0xEA 0x50 0x04 0x00 0x00 0xD5 0x81 0x00 0x00
分析得到序列号为"0x00 0x00 0xA0 0xB8"
分析得到确认号为"0x19 0x2C 0x84 0xEA"
发送"RST数据包"后,发送方会立即关闭连接,而不需要等待对方的确认。接收方收到RST包后,也会立即关闭连接。
