基于TCP协议的网络通讯流程

不多说了,先上个图:

从上面的图中可以看出来,基于TCP协议进行通讯可以大致分成以下几个阶段:

1. 首先是在服务器端, TCP Sever调用socket(), bind(), listen()完成初始化。然后调用accept()阻塞等待,处于监听端口的状态。

2. 客户端调用socket()初始化后,调用connect()发出SYN段并阻塞等待服务器应答,服务器应答一个SYN-ACK段,客户端收到后从connect()返回,

同时应答一个ACK段,服务器收到后从accept()返回。这也就是传说中的TCP三次握手,如下图所示:

TCP 三次握手有一种形象的理解,大家去买手机的时候总要试试手机的通话功能吧, 这时你会走远和你的朋友通话看看质量是否可靠,一般是不是这样:

  • 喂, 听的到吗? (Client)
  • 听的到, 你听的到吗 ? (Server)
  • 嗯, 我也听的到 (Client)

那么就能保证通话质量是OK的, TCP协议也是一样, 通过规定了双方的应答保证了连接的可靠性。

3. 完成三次握手(TCP three way handshake ) TCP Server与TCP Client就建立起了可靠的连接。此后就是Server与Client 数据传输的过程了。因此,服务器从accept()返回

后立刻调用read(),读socket就像读管道一样,如果没有数据到达就阻塞等待,这时客户端调用write()发送请求给服务器,服务器收到后从read()返回,对客户端的请求进行处理,在

此期间客户端调用read()阻塞等待服务器的应答,服务器调用write()将处理结果发回给客户端,再次调用read()阻塞等待下一条请求,客户端收到后从read()返回,发送下一条请

求,如此循环下去。

4. 关闭连接的过程。 如果客户端没有更多的请求了,就调用close()关闭连接,就像写端关闭的管道一样,服务器的read()返回0,这样服务器就知道客户端关闭了连接,也调用

close()关闭连接。注意,任何一方调用close()后,连接的两个传输方向都关闭,不能再发送数据了。如果一方调用shutdown()则连接处于半关闭状态,仍可接收对方发来的数

据。

 贴一个简易的TCP Sever与TCP Client的实现:

 1 /***********************************************************/
 2 /* Copyright (C) SA14226214, USTC, 2014-2015               */
 3 /*                                                         */
 4 /*  FILE NAME             :  server.c                      */
 5 /*  PRINCIPAL AUTHOR      :  GaoZhipeng                    */
 6 /*  SUBSYSTEM NAME        :  lab1                          */
 7 /*  MODULE NAME           :  server                        */
 8 /*  LANGUAGE              :  C                             */
 9 /*  TARGET ENVIRONMENT    :  ANY                           */
10 /*  DATE OF FIRST RELEASE :  2014/12/01                    */
11 /*  DESCRIPTION           :  This is a server program      */
12 /***********************************************************/
13 
14 /*
15  *Revision log:
16  *
17  *Ceated by GaoZhipeng, 2014/12/01
18  *     
19  */
20 
21 #include<stdio.h>
22 #include<stdlib.h>
23 #include<string.h>
24 #include<unistd.h>
25 #include<sys/socket.h>
26 #include<netinet/in.h>
27 
28 #define MAXLINE 80
29 #define SERV_PORT 8000
30 
31 int main(void) 
32 {
33     struct sockaddr_in servaddr, cliaddr;
34     socklen_t cliaddr_len;
35     int listenfd, connfd;
36     char recv_buf[MAXLINE];
37     char *send_buf;
38     char str[INET_ADDRSTRLEN];
39     int i, n;
40 
41     listenfd = socket(AF_INET, SOCK_STREAM, 0);
42 
43     bzero(&servaddr, sizeof(servaddr));
44     servaddr.sin_family = AF_INET;
45     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
46     servaddr.sin_port = htons(SERV_PORT);
47 
48     bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
49     listen(listenfd,20);
50 
51     printf("Accepting connections ...
");
52     cliaddr_len = sizeof(cliaddr);
53     connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
54     while(1)
55     {
56         n = read(connfd, recv_buf, MAXLINE);
57         if(n == 0)
58         {
59             printf("the client has been closed , please restart again
");
60             break;
61         }
62         printf("received from %s at PORT %d ",(char *)inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port));
63 //print the recv_buf on the terminal
64         write(STDOUT_FILENO, recv_buf, n);
65         printf("
");
66 
67         send_buf = "你好世界";
68         write(connfd, send_buf, strlen(send_buf));
69     }
70     close(connfd);
71 
72 }
 1 /***********************************************************/
 2 /* Copyright (C) SA14226214, USTC, 2014-2015               */
 3 /*                                                         */
 4 /*  FILE NAME             :  server.c                      */
 5 /*  PRINCIPAL AUTHOR      :  GaoZhipeng                    */
 6 /*  SUBSYSTEM NAME        :  lab1                          */
 7 /*  MODULE NAME           :  server                        */
 8 /*  LANGUAGE              :  C                             */
 9 /*  TARGET ENVIRONMENT    :  ANY                           */
10 /*  DATE OF FIRST RELEASE :  2014/12/01                    */
11 /*  DESCRIPTION           :  This is a server program      */
12 /***********************************************************/
13 
14 /*
15  *Revision log:
16  *
17  *Ceated by GaoZhipeng, 2014/12/01
18  *     
19  */
20 
21 #include<stdio.h>
22 #include<stdlib.h>
23 #include<string.h>
24 #include<unistd.h>
25 #include<sys/socket.h>
26 #include<netinet/in.h>
27 
28 #define MAXLINE 80
29 #define SERV_PORT 8000
30 
31 int main(int argc, char *argv[]) 
32 {
33     struct sockaddr_in servaddr;
34     char buf[MAXLINE];
35     int sockfd, n;
36 
37     sockfd = socket(AF_INET, SOCK_STREAM, 0);
38 
39     bzero(&servaddr, sizeof(servaddr));
40     servaddr.sin_family = AF_INET;
41     inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
42     servaddr.sin_port = htons(SERV_PORT);
43 
44     connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
45 
46     printf("input you message (q to exit): ");
47 
48     //ŽÓ±ê׌ÊäÈëÉ豞ÖжÁÈ¡×Ö·ûŽ®ÐŽÈëbuf
49     while(fgets(buf, MAXLINE, stdin) != NULL) {
50         if(buf[0] == 'q' && strlen(buf) == 2)
51         {
52             break;
53         }
54         write(sockfd, buf, strlen(buf));
55 
56         n = read(sockfd, buf, MAXLINE);
57         if(n == 0)
58         {
59             printf("the connect side has been closed. please run it again
");
60             exit(0);
61         }
62         write(STDOUT_FILENO, "Response from server : ", sizeof("Response from server : "));
63         write(STDOUT_FILENO, buf, n);
64         printf("
input you message (q to exit): ");
65     }
66     close(sockfd);
67     return 0;
68 }

一个简单的MakeFile :

/*           makefile               */
all :
        gcc server.c -o server
        gcc client.c -o client

clean :
        rm server client
原文地址:https://www.cnblogs.com/beyond-Acm/p/4365345.html