一、了解TCP结构
下图是TCP首部分析图, 有6个格外显眼的图标, 接下来我们将会按着给大家分析其中的每个属性, 以及URG标志
图一
1)、源端口和目的端口各两个字节。
2)、序号:占4个字节(unsigned int一样的取值范围), 它是用来给TCP报文编号用的。 如果本次报文的序号为x, 并且携带的数据是y字节。 那么下一个数据报的序号就为x+y。若是序号的值超过了unsigned int的最大啊范围值, 那么就对其进行求余运算而得到新的序号。
3)、确认号:占4个字节(unsigned int一样的取值范围), 它是用来期望收到对方下一个报文段的第一个数据字节的序号。例如, 当B收到了A发来的报文段中, 其序号为1000, 数据长度为250(序号1000-1249), 那么确认号为1250, 这表明B收到A发出的到序号1249为止的数据。 因此B希望收到的下一个数据序号1250。
4)、紧急URG:当URG为1的时候, 表明紧急指针字段有效。 它告诉系统次报文中含有紧急数据, 应当尽快传送。
5)、确认ACK:仅当ACK等于1的时候, 当前字段才有效,等于0 的确认字段无效。 TCP中若是已经连接, 那么所有的ACK必须置为1.
6)、推送PSH:在进程通讯的时候, 当短文发送完毕后, 通过PSH置为1, 通知进程可以接受数据, 不用等到缓冲区已满。
7)、复位RST:当RST = 1的时候, 表示TCP连接出现严重错误(如主机崩溃或者其他原因), 必须释放该链接, 然后重新建立连接。RST 置为1还用来拒绝一个非法的报文段或者拒绝打开连接。
8)、同步SYN:在连接建立用来同步序号。
9)、终止FIN:当断开连接的时候, 同步信号。
10)、窗口: 占有两个字节的整数(unsigned short),该窗口值指的是对方接收端口的值。窗口值:用来告诉对方从本报文中的人确认号算起, 接收方能够允许对方的发送的数据量。总之, 窗口值作为接收方让发送方设置窗口数据的依据。例如:如果确认号为1250, 窗口字段是1000, 那么表明, 从1250算起, 发送此报文段的一方还有1000个字节数据(1250-2249)的接受缓冲空间。 通俗的说法:就是告诉对方我还能接受多少你的数据大小。
12)、紧急指针:当URG = 1, 该指针有效, 支出本报文中的紧急数据的字节数
二、带外数据和URG标志
通常在报文中,通过紧急指针标志外快数据,标记的字节大小为一字节, 所以带外数据为一字节, 我们通过紧急指针来标记数据。
紧急数据字节号 = 报文序号 + 紧急指针 - 1。
我们通过客户端向服务器发送数据:
伪代码如下:
for(i = 0; i < 8; ++i){
if(i == 4) send(sockfd, "U", 1, MSG_OOB);
send(sockfd, sendbuf, 1000, 0);
}
while(true){
n = read(sockfd, buf, MAXLINE);
if(n < 0){
if(errno == EINTR) continue;
else{
fprintf(stderr, "read error from socket\n");
break;
}
}
else if(n == 0) break;
else{
// write(sockfd, buf, n);
}
}
运行结果的抓包如下:
抓包结果分析:
1、Flags [P.],表示开启了PSH标志, 如果是Flags[P.U], 表示PSH, URG标志有效,。
2、如抓包结果图中的seq1:1001表示该报文序号为1, 确认号为1001, 确认号, 为下一个报文的序号。所有的TCP报文其ACK必须置为1。
3、服务端确认该报文已收到的时候会发送一个数据长度为0, ack = 确认号的报文段。
4、第二个箭头中, length= 3001, 表示内核自动那四次send。用一个数据报运载, 那是应为触发了Nagle算法。