我在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上。 现在我应该如何保持连接?
至少有两件事需要考虑。
首先,默认时间的 SO_KEEPALIVE 甚至不会在 2 小时过去且没有任何活动的情况下启动。是的,没错——是两个小时,不是分钟,不是秒。
通常,连接中的其他实体会比这更快地断开连接。
其次,keepalive工作在TCP层面。应用程序通常有自己的超时 - 它们不希望连接在没有发生任何事情时保持打开状态。
一般来说,具有开放但看似空闲连接的有效用例的协议可能会实现“心跳”类型的方案:它们仍然会在没有发生任何事情的情况下放弃连接(以捕获仍然有网络故障或崩溃的客户端)打开连接),但支持特殊的“心跳”/“ping”数据包/命令,实际上不执行任何操作,但您可以每隔几秒左右发送一次,以防止连接“空闲”。