• TCP包结构

  一个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三次握手过程:

  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 } 
View Code

相关文章:

  • 2021-04-29
  • 2021-04-02
  • 2021-04-19
猜你喜欢
  • 2021-07-12
  • 2022-12-23
  • 2021-04-30
  • 2021-04-08
  • 2021-10-08
  • 2021-10-17
相关资源
相似解决方案