32. TCP异常之三次握手


本节来重现TCP可能出现异常的原因中部分为三次握手的出现的问题.


服务端没有监听

服务端没有监听, 客户端发送ACK而服务端TCP协议返回一个RST段, 客服端调用connect返回错误, 错误类型是ECONNREFUSED.

这个实验随便之前的哪一个代码都可以, 只运行客户端的程序, 抓包就可以看到 :

在这里插入图片描述

SYN后没收到ACK确认报文

客户端一直没有收到对端的ACK确认报文, 当超时后继续发送FIN, 多次失败之后客户端停止尝试连接并且客户端connect函数返回错误, 错误类型是ETIMEOUT.


ECONNABORTED

三次握手成功了, 但是客户端立马发送一个RST段后断开而服务端处于繁忙状态, 等服务端返回时才发现对端已经关闭, 此时服务端也关闭. 客户端connect后立即断开, 服务端在accept函数返回前收到RST段, 则accept函数返回ECONNABORTED(该错误errno依赖操作系统).

完整代码 accept_ECONNABORTED.c.

这里罗列的代码 :

服务端在listen之后, accept之前睡眠5秒.

// 服务端
int service(int port, const char *ser_addr)
{
    int sockfd, clientfd;
    sockfd = Socket(0);
    Bind(sockfd, port, ser_addr);
    listen(sockfd, 1);

    struct sockaddr_in client_addr;
    socklen_t client_len = sizeof(client_addr);

    
    sleep(5);

    return 0;
}


客户端调用setsockopt函数, 设置SO_LINGER, 客户端在 close 的时候不是发送 FIN, 而是RST.

// 客户端
int client(int port, const char *cli_addr)
{
    int sockfd;
    sockfd = Socket(0);
    Connect(sockfd, port, cli_addr);

    // 设置套接字选项
    struct linger lig;
    lig.l_onoff = 1;
    lig.l_linger = 0;
    // 客户端在 close 的时候不是发送 FIN,而是 RST.
    if(setsockopt(sockfd, SOL_SOCKET, SO_LINGER, (void *)&lig, sizeof(lig)) != 0)
		EXIT("setsockopt");


    return 0;
}

运行时客户端后马上中断连接, 可以抓包看到, 客户端发送的不是FIN.

在这里插入图片描述

在这里插入图片描述


总结

还有很多错误的可能性没有整理, 但也不好实验, 所以三次握手的问题就暂时这些吧.

你可能感兴趣的:(网络编程,网络编程学习)