tcp 连接空闲超时

问题描述 投票:0回答:1

我在Windows上有一些客户端和一个服务器(我对客户端和服务器都使用winsock),服务器正在等待客户端通过tcp连接到它, 在与传入客户端建立连接并等待其他客户端后等待近 5 分钟时,连接从服务器端关闭,recv 返回错误代码 10053,在客户端 recv 返回 0。 我尝试在服务器和客户端中设置 SO_KEEPALIVE 选项,但它不起作用。服务器在 AWS 上的虚拟机上运行。

这是服务器代码:用于在侦听套接字中打开套接字选项

struct addrinfo hints1;
    memset(&hints1, 0, sizeof(hints1));
    hints1.ai_family = AF_INET;
    hints1.ai_socktype = SOCK_STREAM;
    hints1.ai_flags = AI_PASSIVE;
    struct addrinfo* bind_addres;
    int port2 = port + 3;//8081+3=8084 is the port of the tcp connection
    char port2_str[10];
    sprintf(port2_str, "%d", port2);
    getaddrinfo(0, port2_str, &hints1, &bind_addres);//this server is running on port 8080

    SOCKET tcp_socket = socket(bind_addres->ai_family, bind_addres->ai_socktype, bind_addres->ai_protocol);
    if (!ISVALIDSOCKET(tcp_socket))
    {
        cout << "\n socket not created=>" << GETSOCKETERRNO();
    }
    int enableKeepAlive = 1;
    setsockopt(tcp_socket, SOL_SOCKET, SO_KEEPALIVE, (const char*)&enableKeepAlive, sizeof(enableKeepAlive));

    cout << "\n binding the socket==>";
    if (bind(tcp_socket, (const sockaddr*)bind_addres->ai_addr, (int)bind_addres->ai_addrlen))
    {
        cout << "\n failed to bind the socket==>" << GETSOCKETERRNO();
    }

这里是打开已连接套接字中的套接字选项的服务器代码:

struct sockaddr_storage client_address;
                    socklen_t client_len = sizeof(client_address);
                    SOCKET client = accept(tcp_socket, (sockaddr*)&client_address, &client_len);
                    int enableKeepAlive = 1;
                    setsockopt(client, SOL_SOCKET, SO_KEEPALIVE, (const char*)&enableKeepAlive, sizeof(enableKeepAlive));

socket客户端的代码是:

struct addrinfo hints;
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    struct addrinfo* bind_address;
    int port2 = port + 3;
    char port2_str[10];
    sprintf(port2_str, "%d", port2);
    //cout << "\n port of the server2 is==>" << port2_str;
    getaddrinfo(ip_address.c_str(),port2_str, &hints, &bind_address);
    cout << "\n tcp connection port is=>" << port2_str;
    SOCKET tcp_socket = socket(bind_address->ai_family, bind_address->ai_socktype, bind_address->ai_protocol);
    if (!ISVALIDSOCKET(tcp_socket))
    {
        fprintf(stderr, "socket() failed. (%d)\n", GETSOCKETERRNO());
        //return 1;
    }
    int enableKeepAlive = 1;
    setsockopt(tcp_socket, SOL_SOCKET, SO_KEEPALIVE, (const char*)&enableKeepAlive, sizeof(enableKeepAlive));

开启SO_KEEPALIVE后,大约5分钟后连接就断开了,连接在服务器端断开。

服务器主机上的Windows防火墙可能已打开。服务器托管在AWS VM上。 现在我应该如何保持连接?

c++ sockets winsock
1个回答
0
投票

至少有两件事需要考虑。

首先,默认时间的 SO_KEEPALIVE 甚至不会在 2 小时过去且没有任何活动的情况下启动。是的,没错——是两个小时,不是分钟,不是秒。

通常,连接中的其他实体会比这更快地断开连接。

其次,keepalive工作在TCP层面。应用程序通常有自己的超时 - 它们不希望连接在没有发生任何事情时保持打开状态。

一般来说,具有开放但看似空闲连接的有效用例的协议可能会实现“心跳”类型的方案:它们仍然会在没有发生任何事情的情况下放弃连接(以捕获仍然有网络故障或崩溃的客户端)打开连接),但支持特殊的“心跳”/“ping”数据包/命令,实际上不执行任何操作,但您可以每隔几秒左右发送一次,以防止连接“空闲”。

© www.soinside.com 2019 - 2024. All rights reserved.