三次握手
由 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. 建立连接三次握手
2. 数据传输阶段
client server
(1)SYN_SENT ========> (2)LISTEN
(4)ESTABLISHED <======== (3)SYN_RCVD
(5) =========> (6)ESTABLISHED
3. 断开连接四次挥手
使用 netstat 命令查看各种状态:
(1)FIN_WAIT_1 =========> (2)CLOSE_WAIT
(4)FIN_WAIT_2 <========== (3)
(6)TIME_WAIT <========== (5)LAST_ACK
(7) ==========>
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;
}
来源: https://www.cnblogs.com/taoshihan/p/8306594.html