- TCP包结构
一个TCP包结构如下:
一个TCP包主要由TCP包头和数据部分组成,包头固定部分为20字节,选项和数据部分根据实际情况设置为4N(N可以为0)字节。
1.16bit源端口和目的端口号,它可以确认数据的传输方向(暂不考虑更底层的包)
2.32bit序号,它是为TCP包中数据部分进行编号的部分。假设要发送的数据有100M,由于受MSS( Maximum Segment Size 最大报文段长度)限制,一个TCP包是不可能传输完这100M的数据,于是需要将数据拆分,为了确保拆分传输后的数据能在接收端正确的拼接,就需要对每个拆分的数据包进行编号来传输。这样,这个32位的序号指的就是本包数据部分第一个字节是这个100M数据中的第多少个字节。例如:假设发送第一个包时,先取出这100M数据的前面1024个字节发送,这时这个包中32位序号就是1,然后取下一个1024字节传输,这个时候的数据部分的第一个字节是这100M数据的第1025个字节,所以这第二TCP包中32位的序列号就应该为1025。当序号超过2^32时,进行一个轮回,重新从0开始计数。
3.32bit确认序号,和上面的32位序号类似,只不过它指的是期望收到的下一个包的数据部分的编号。
4.4bit首部长度,单位为4字节,指的是一个TCP包中除去数据部分的长度,也就是包头固定部分+选项部分的长度,2^4 -1 = 15, 15*4字节=60字节,即包头固定部分为20字节,选项最多可以为40字节。
5.标识位:
URG:.........
ACK:TCP包的Acknowledgement number有效位,1时表明Acknowledgement number有效,0表示Acknowledgement number无效,忽略Acknowledgement number字段。自tcp连接建立后,ACK必须为1。
PSH:TCP包中有数据需要尽快传递给应用层使用,而不是将数据进行缓冲,等到缓冲区满了再投递给应用层。
RST:..........
SYN:TCP包的同步位
FIN:表示这个方向的带数据的包传输已经完成,即发送FIN包的端没有带数据的包过来了,需要释放这个方向的连接。
- TCP三次握手
TCP三次握手过程:
测试代码,server端:
1 #include <stdio.h> 2 #include <string.h> 3 #include <sys/types.h> 4 #include <sys/socket.h> 5 #include <netinet/in.h> 6 7 #define ECHO "yes,i see you!" 8 9 int main ( int argc, char *argv[] ) 10 { 11 int ret,rn; 12 int socketfd,acfd; 13 int socklen; 14 char buf[1024]; 15 16 struct sockaddr_in hostaddr; 17 struct sockaddr_in clientaddr; 18 19 socketfd = socket(AF_INET, SOCK_STREAM, 0); 20 if ( socketfd < 0 ) 21 { 22 perror("socket"); 23 return -1; 24 } 25 26 memset((void *)&hostaddr, 0, sizeof(hostaddr)); 27 hostaddr.sin_family = AF_INET; 28 hostaddr.sin_port = htons(6666); 29 hostaddr.sin_addr.s_addr = htonl(INADDR_ANY); 30 31 ret = bind(socketfd, (struct sockaddr *)&hostaddr, sizeof(hostaddr)); 32 if ( ret < 0 ) 33 { 34 perror("bind"); 35 close(socketfd); 36 return -1; 37 } 38 39 ret = listen(socketfd, 5); 40 if ( ret < 0 ) 41 { 42 perror("listen"); 43 close(socketfd); 44 return -1; 45 } 46 47 socklen = sizeof(struct sockaddr); 48 acfd = accept(socketfd, (struct sockaddr *)&clientaddr, &socklen); 49 if ( acfd < 0 ) 50 { 51 perror("accept"); 52 close(socketfd); 53 return -1; 54 } 55 56 while (1) 57 { 58 memset(buf, 0x0, sizeof(buf)); 59 rn = read(acfd, buf, sizeof(buf)); 60 printf("%s\n",buf); 61 } 62 //write(acfd, ECHO, sizeof(ECHO)); 63 64 close(acfd); 65 close(socketfd); 66 67 return 0; 68 }