检查插座是否已连接

opc*_*0de 17 c c++ sockets connection

我有一个应用程序需要在某个时间将一些数据发送到服务器.简单的方法是关闭连接,然后当我想发送东西时再次打开它.但是我想保持连接打开,所以当我想发送数据时,我首先使用这个函数检查连接:

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

不好的是,这不起作用.当没有数据要接收时它会挂起.我能做什么?如何检查连接是否仍然打开?

Dav*_*rtz 24

不要先检查再发送.这是浪费的努力,无论如何都无法工作 - 状态可以在您检查和发送时间之间发生变化.只要做你想做的事情,如果失败就处理错误.

要检查状态,请使用:

int error_code;
int error_code_size = sizeof(error_code);
getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, &error_code, &error_code_size);
Run Code Online (Sandbox Code Playgroud)

  • @che右,所以请使用它进行检查.然后,如果它不活着,你可以停止浪费资源.检查本身就是浪费资源. (10认同)
  • @RafaelBaptista为什么?*使用*它会检查.由于David在上面给出的原因,首先测试不能可靠地工作. (4认同)
  • @seth你用*来做* (3认同)
  • 是的......但有时检查套接字是否仍然连接是有用的.将其设置为非阻塞,然后使用peek_msg读取是一种引出错误代码以检查套接字是否仍然连接的好方法. (2认同)
  • 100% 的用例都用于检查连接状态 - 只是不像已经说明的那样作为预发送例程。有时您需要知道连接丢失的时间以便向用户报告 - 不仅仅是发送失败时 (2认同)

cni*_*tar 12

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

recv(sock, &buf, 1, MSG_PEEK | MSG_DONTWAIT);
Run Code Online (Sandbox Code Playgroud)

之后,您必须检查errno是否失败.它可能会失败,EAGAIN或者它可能会失败EBADFENOTCONN等等.


显然,处理这个问题最简单,最干净的方法是避免"忘记"套接字是否连接.一旦recv返回0或send返回,您将注意到套接字是否断开连接EPIPE.

  • 这不会检测到所有连接故障.只有send()可以做到这一点. (2认同)

mar*_*ark 5

默认使用 TCP 不允许非常及时地检测死套接字(在正常关闭之外),因此我建议像这样的“is_connected”函数对于所有实际目的来说基本上是无用的。考虑实施应用程序层保持活动状态,并根据及时响应(或缺乏响应)来跟踪它是否处于活动状态。

编辑:发布后我看到 BoBTFish 的链接,这实际上是同一件事。