• [linux] C语言Linux系统编程-TCP通信的11种状态


    三次握手
    由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
    ", 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;
    }
  • 相关阅读:
    (转)Centos7安装Docker
    Rust一些设计的不好的地方
    Maven pom.xml的properties配置
    进程从硬盘读取文件的过程
    监控日志并上报阿里云日志服务
    rsyslog 系统日志收集上报(可增加自定义项目日志)
    获取Linux mac地址(centos与ubuntu通用)
    shell 判断操作系统
    9999
    【2022.01.18】树莓派几个好用适合的docker
  • 原文地址:https://www.cnblogs.com/taoshihan/p/8306594.html
Copyright © 2020-2023  润新知