如何在C中查找套接字连接状态?
我有一个TCP连接。服务器只是从客户端读取数据。现在,如果连接丢失,客户端将在将数据写入管道(断开的管道)时出错,但服务器仍在侦听该管道。是否有任何方法可以确定连接是否已打开?您可以按如下方式调用getsockopt:如何在C中查找套接字连接状态?,c,network-programming,C,Network Programming,我有一个TCP连接。服务器只是从客户端读取数据。现在,如果连接丢失,客户端将在将数据写入管道(断开的管道)时出错,但服务器仍在侦听该管道。是否有任何方法可以确定连接是否已打开?您可以按如下方式调用getsockopt: int error = 0; socklen_t len = sizeof (error); int retval = getsockopt (socket_fd, SOL_SOCKET, SO_ERROR, &error, &len); 要测试插座是否打开,请
int error = 0;
socklen_t len = sizeof (error);
int retval = getsockopt (socket_fd, SOL_SOCKET, SO_ERROR, &error, &len);
要测试插座是否打开,请执行以下操作:
if (retval != 0) {
/* there was a problem getting the error code */
fprintf(stderr, "error getting socket error code: %s\n", strerror(retval));
return;
}
if (error != 0) {
/* socket has a non zero error status */
fprintf(stderr, "socket error: %s\n", strerror(error));
}
对于BSD插座,我想退房。当recv返回0时,您知道另一侧已断开连接
现在你可能会问,检测另一侧断开连接的最简单方法是什么?一种方法是让线程始终执行recv。当客户端断开连接时,该线程将能够立即判断 TCP keepalive套接字选项(SO_keepalive)在这种情况下会有所帮助,并在连接丢失时关闭服务器套接字。可靠检测套接字是否仍然连接的唯一方法是定期尝试发送数据。定义客户端忽略的应用程序级“ping”数据包通常更方便,但是如果已经指定了没有这种功能的协议,那么您应该能够通过设置套接字选项来配置tcp套接字来实现这一点。我已经链接到winsock文档,但是在所有类似BSD的套接字堆栈上都应该有相同的功能。我遇到了类似的问题。我想知道服务器是连接到客户端还是客户端连接到服务器。在这种情况下,recv函数的返回值可以派上用场。如果套接字未连接,它将返回0字节。因此,我使用它打破了循环,不必使用任何额外的函数线程。如果专家认为这是正确的方法,你也可以使用同样的方法 获取sock opt可能有些有用,但是,另一种方法是为SIGPIPE安装信号处理程序。基本上,每当套接字连接中断时,内核都会向进程发送一个SIGPIPE信号,然后您就可以执行所需的操作。但这仍然不能提供了解连接状态的解决方案。希望这有帮助。您应该尝试使用:getpeername函数 现在,当连接断开时,您将进入errno: ENOTCONN-套接字未连接。 这意味着你会失望 否则(如果没有其他故障),返回代码将为0-->这意味着向上 资源:
手册页:您可以在
getsockopt()
函数中使用SS\u ISCONNECTED
宏。
SS_ISCONNECTED
是在socketvar.h
中定义的,有一种简单的方法可以通过poll
调用检查套接字连接状态。首先,您需要轮询套接字,它是否有POLLIN
事件
read
将返回大于零的值POLLIN
将在revents
POLLIN
标志将设置为1,read将返回0int client_socket_1, client_socket_2;
if ((client_socket_1 = accept(listen_socket, NULL, NULL)) < 0)
{
perror("Unable to accept s1");
abort();
}
if ((client_socket_2 = accept(listen_socket, NULL, NULL)) < 0)
{
perror("Unable to accept s2");
abort();
}
pollfd pfd[]={{client_socket_1,POLLIN,0},{client_socket_2,POLLIN,0}};
char sock_buf[1024];
while (true)
{
poll(pfd,2,5);
if (pfd[0].revents & POLLIN)
{
int sock_readden = read(client_socket_1, sock_buf, sizeof(sock_buf));
if (sock_readden == 0)
break;
if (sock_readden > 0)
write(client_socket_2, sock_buf, sock_readden);
}
if (pfd[1].revents & POLLIN)
{
int sock_readden = read(client_socket_2, sock_buf, sizeof(sock_buf));
if (sock_readden == 0)
break;
if (sock_readden > 0)
write(client_socket_1, sock_buf, sock_readden);
}
}
int client_socket_1,client_socket_2;
如果((客户端\u套接字\u 1=accept(侦听\u套接字,NULL,NULL))<0)
{
perror(“无法接受s1”);
中止();
}
if((客户端\u套接字\u 2=accept(侦听\u套接字,NULL,NULL))<0)
{
perror(“无法接受s2”);
中止();
}
pollfd pfd[]={{client_socket_1,POLLIN,0},{client_socket_2,POLLIN,0};
char sock_buf[1024];
while(true)
{
投票(pfd,2,5);
if(pfd[0]。revents和POLLIN)
{
int sock_readden=read(client_socket_1,sock_buf,sizeof(sock_buf));
if(sock_readden==0)
打破
如果(sock_readden>0)
写入(客户端套接字2、套接字buf、套接字readden);
}
if(pfd[1]。收入和收入)
{
int sock_readden=read(client_socket_2,sock_buf,sizeof(sock_buf));
if(sock_readden==0)
打破
如果(sock_readden>0)
写入(客户端套接字1、套接字buf、套接字readden);
}
}
非常简单,如图中所示
要检查是否需要使用MSG\u PEEK
和MSG\u DONT\u WAIT
从套接字读取1字节。这不会使数据出列(PEEK
),并且操作是非阻塞的(DONT_WAIT
)
找到示例。在Windows上,您可以使用以下命令查询任何网络适配器上任何端口的精确状态: 您可以将其过滤到与流程等相关的内容,并根据需要定期监控。这是一种“替代”方法
您还可以复制套接字句柄,在套接字上设置IOCP/重叠i/o等待,并以这种方式对其进行监视。我认为您应该澄清是为windows还是linux/unix开发。发送错误结果时,您应该首先检查它实际上是什么错误,然后确定这是否是一个可恢复的错误(也许它能自己修复吗?)或者,如果这意味着您的连接肯定已断开。如果确实已断开,请关闭套接字。如果您仍然可以获得任何流量,则另一方将看到套接字已关闭。如果无法获得任何流量,则仍将丢失。在这种情况下,另一方可以注意到的唯一方法是发送本身应触发的内容一个回复,如果没有这样的回复,那么另一方就死了。不,不会。tcp堆栈只能在以下情况下检测套接字是否关闭:(a)它接收到来自另一方的数据包,或者(b)等待已发送数据包的ack时超时。对于recv,如果中间路由器停机或远程主机异常关闭套接字(未发送关闭消息),将不会有数据包到达以警告套接字堆栈recv正在等待关闭连接。但它不会检测到无声中断的套接字。常见的情况是,中间的NAT网关超时连接(和)
while (recv(client->socket,NULL,1, MSG_PEEK | MSG_DONTWAIT) != 0) {
sleep(rand() % 2); // Sleep for a bit to avoid spam
fflush(stdin);
printf("I am alive: %d\n", socket);
}
// When the client has disconnected, this line will execute
printf("Client %d went away :(\n", client->socket);