三次握手由client主動發出SYN請求, 此時client處於SYN_SENT狀態(第一次握手)當server收到之後會由LISTEN轉變為SYN_REVD狀態, 並回覆client, client收到應答後處於ESTABLISHED狀態, 這個狀態就表示client已經準備好通信了(第二次握手) ...
三次握手
由client主動發出SYN請求, 此時client處於SYN_SENT狀態(第一次握手)
當server收到之後會由LISTEN轉變為SYN_REVD狀態, 並回覆client, client收到應答後處於ESTABLISHED狀態, 這個狀態就表示client已經準備好通信了(第二次握手)
client收到二次握手應答後回覆server, server收到應答之後也處於ESTABLISHED, 表示握手成功, 可以通信了(第三次握手)
數據傳輸
然後client和server都處於通信狀態, 不會改變
四次揮手
client主動發送FIN請求關閉, 此時client處於FIN_WAIT_1狀態(短暫)(第一次揮手)
server收到之後處於CLOSE_WAIT狀態(半關閉狀態), 並做出應答(第二次揮手)
client收到之後處於FIN_WAIT_2狀態, 等待server發送關閉請求.
server會緊接著發送FIN斷開請求, 並處於LAST_ACK(第三次揮手)
client收到之後並應答, 此時處於TIME_WAIT狀態, 這是主動斷開的一端的最後一個狀態, 意思是會等待一定的時間(2MSL-1min), 等待之後會變成CLOSED狀態(第四次揮手)
TCP的11種狀態
CLOSED最初狀態
1.建立連接三次握手
client server
(1)SYN_SENT ========> (2)LISTEN
(4)ESTABLISHED <======== (3)SYN_RCVD
(5) =========> (6)ESTABLISHED
2.數據傳輸階段
3.斷開連接四次揮手
(1)FIN_WAIT_1 =========> (2)CLOSE_WAIT
(4)FIN_WAIT_2 <========== (3)
(6)TIME_WAIT <========== (5)LAST_ACK
(7) ==========>
使用netstat命令查看各種狀態:
1.
2.
3.
4.
服務端監聽本機1234埠,客戶端進行連接,TIME_WAIT狀態維持時間是兩個MSL時間長度,也就是在1-4分鐘,自動關掉
參照代碼:
client.c
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> int main(){ //創建套接字 int sock = socket(AF_INET, SOCK_STREAM, 0); sleep(20); //向伺服器(特定的IP和埠)發起請求 struct sockaddr_in serv_addr; memset(&serv_addr, 0, sizeof(serv_addr)); //每個位元組都用0填充 serv_addr.sin_family = AF_INET; //使用IPv4地址 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具體的IP地址 serv_addr.sin_port = htons(1234); //埠 connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); sleep(20); //讀取伺服器傳回的數據 char buffer[40]; read(sock, buffer, sizeof(buffer)-1); printf("Message form server: %s\n", buffer); //sleep(60); //關閉套接字 close(sock); sleep(60); return 0; }
server.c
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <netinet/in.h> int main(){ //創建套接字 int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //將套接字和IP、埠綁定 struct sockaddr_in serv_addr; memset(&serv_addr, 0, sizeof(serv_addr)); //每個位元組都用0填充 serv_addr.sin_family = AF_INET; //使用IPv4地址 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);; //具體的IP地址 serv_addr.sin_port = htons(1234); //埠 bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); //進入監聽狀態,等待用戶發起請求 listen(serv_sock, 20); sleep(20); //接收客戶端請求 struct sockaddr_in clnt_addr; socklen_t clnt_addr_size = sizeof(clnt_addr); int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size); sleep(20); //向客戶端發送數據 char str[] = "Hello World!"; write(clnt_sock, str, sizeof(str)); sleep(20); //關閉套接字 close(clnt_sock); sleep(20); close(serv_sock); sleep(20); "5.c" 36L, 1183C 1,1 Top close(serv_sock); sleep(20); return 0; }