检查套接字是否已连接

29

我有一个应用程序需要在某个时候向服务器发送一些数据。最简单的方法是在想要发送数据时关闭连接,然后再次打开它。但我想保持连接处于打开状态,这样当我想要发送数据时,首先使用此函数检查连接:

bool is_connected(int sock)
{
    unsigned char buf;
    int err = recv(sock,&buf,1,MSG_PEEK);
    return err == -1 ? false : true;
}

糟糕的是,这样做行不通。 当没有数据可接收时,它会挂起。 我该怎么办? 如何检查连接是否仍然打开?


4
如何在C中找到套接字连接状态?要找到套接字连接状态,需要使用SO_ERROR选项。以下是一个示例代码段:int error = 0; socklen_t len = sizeof (error); int retval = getsockopt (socket_fd, SOL_SOCKET, SO_ERROR, &error, &len); if (retval != 0) { // 处理getsockopt错误 perror("getsockopt"); return -1; } if (error != 0) { // 套接字连接出现错误 fprintf(stderr, "socket error: %s\n", strerror(error)); return -1; } // 套接字连接成功 return 0; - BoBTFish
3个回答

35

不要先检查再发送。这是浪费功夫,而且也不会起作用——状态可能会在你检查和发送之间发生变化。只需做你想做的事情,如果失败了则处理错误。

要检查状态,请使用:

int error_code;
int error_code_size = sizeof(error_code);
getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, &error_code, &error_code_size);

2
正确...但有时检查套接字是否仍然连接是很有用的。将其设置为非阻塞,然后使用peek_msg进行读取是一种很好的方式,以引发错误代码来检查套接字是否仍然连接。 - Rafael Baptista
4
@RafaelBaptista 为什么?使用它将进行检查。首先进行测试不能可靠地工作,这是David在上面提到的原因。 - user207421
12
@che,没错,使用它来检查。如果它没有响应,你可以停止浪费资源。检查本身就是一种资源浪费。 - David Schwartz
5
你需要通过使用它来完成。 - David Schwartz
2
检查连接状态有100%的使用情况 - 只是不像先前所述那样作为预发送例程。有时您需要知道连接丢失的时间,以便向用户报告,而不仅在发送失败时。 - Danaldo
显示剩余4条评论

13

您需要启用非阻塞行为,通过使用 fcntl 设置 O_NONBLOCK。一种简单但非标准的进行非阻塞读取的方法是使用:

recv(sock, &buf, 1, MSG_PEEK | MSG_DONTWAIT);

之后,如果它失败了,你必须检查errno。它可能会失败并显示EAGAIN或者EBADFENOTCONN等。


显然,处理这个问题最简单和最干净的方法是避免“忘记”套接字是否连接。一旦recv返回0或send返回EPIPE,你就会注意到套接字是否已断开连接。


3
这不会检测到所有的连接失败。只有通过send()才能实现。 - user207421
1
@EJP 实际上是这样的。我只是在改进原始问题的解决方案。你所建议的是唯一可靠的解决方案,但它需要发送。 - cnicutar
另外值得一提的是,由于我们使用了MSG_DONTWAIT标志,因此我们不需要单独使用fcntl()系统调用通过O_NONBLOCK标志将套接字标记为非阻塞:MSG_DONTWAIT在这里使套接字变为非阻塞。 - avernus

5

TCP的默认使用不允许非常及时地检测到死亡套接字(除了正常关闭之外),因此我建议这样的“is_connected”函数在实际用途中基本上是没有用处的。考虑实现一个应用层keep-alive,并根据及时响应(或缺乏响应)来跟踪其是否存活。

编辑:发布后,我看到BoBTFish的链接,它实际上是相同的东西。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接