【问题标题】:Check of socket closure检查插座闭合
【发布时间】:2016-02-13 19:56:37
【问题描述】:

我有一个连接到某个服务器的应用程序。它可以同步发送数据(发送和等待应答)和异步接收数据。 我做了2个线程。在无限循环的第一个线程中,我发送数据并等待答案。在第二个线程中,我从服务器获取数据并将它们推送到队列中。 但是,如果在我发送数据时(在第一个线程中)发生了一些错误,我必须关闭套接字。以及如何检查套接字已关闭的第二个线程?

第二个线程中的代码:

while (processing) {
  nbytes = recv(socketDesc, canFrame, sizeof(data), 0);
  if (nbytes > 0) {
    push_queue(data);
  }
  if (nbytes < 0) {
    throw "Error in read data from socket!";
  }
}

如果我在第二个线程函数recv 的第一个线程中关闭套接字不会出错。现在我使用超时,像这样:

setsockopt(this->socketDesc, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
  setsockopt(this->socketDesc, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv));

当我没有从服务器(在第一个线程中)得到答案时发生错误时,我将变量 processing 设置为 false 并且在超时到期后(在函数 recv 中)循环结束。我可以在函数recv 中一次检查套接字关闭吗?

【问题讨论】:

  • 如何关闭套接字?使用关闭()?您是否尝试过使用 shutdown() 代替? shutdown() 具有丢弃挂起的读取和/或写入数据的选项,因此可以提供帮助。

标签: c++ linux sockets


【解决方案1】:

无法及时确定您已关闭套接字。您需要一个在两个线程之间共享并受互斥锁保护的变量。第一个线程可以设置变量,如果它关闭套接字,第二个线程应该在做recv之前检查它。

【讨论】:

  • 那么,我必须对 setsockopt. 使用 SO_RCVTIMEO 和 SO_SNDTIMEO 设置来完成 recv 函数并将第二个线程签入共享变量?
  • 否,在您即将关闭套接字时设置共享变量,并在尝试recv 之前在另一个线程中检查它。你不需要超时。
  • 嗯。如果不在 recv 中使用超时,即使套接字关闭,它也会无限工作。
  • 为什么?当您知道套接字已关闭时,您不会执行recv。而且您知道套接字已关闭,因为您在关闭它之前设置了共享变量。
  • 否,示例:启动了一个应用程序。两个线程也都启动了。在第二个线程中recv 正在等待来自服务器的传入数据。在第一个线程中,我发送数据但没有得到答案。我关闭了套接字,但 recv 正在工作。在这种情况下,我必须停止recv,因为我使用超时。
【解决方案2】:

这是确保在读取线程正在读取时不关闭套接字的方法。

您有 2 个受互斥锁保护的共享布尔变量:

bool reading = false;
bool closed = false;

所有对这些的访问都在锁定互斥体之前,并通过解锁它成功。

写作线程:

  1. 写入
  2. 如果写入失败:
    1. closed 设置为true
    2. 等待reading变成false
    3. 关闭套接字

阅读线程:

  1. 检查closed 不是true。如果不是:
    1. reading 设置为true
    2. 读取
    3. reading 设置为false

【讨论】:

  • 我很抱歉,但我仍然不明白......如果我调用recv,它将在它没有获取数据时工作。即使不向服务器发送请求,数据也可以来。我必须永久检查来自服务器的传入数据。
  • 如果我将在recv 中使用超时,我可以检查套接字的状态,如果它关闭,我会完成循环,或者如果套接字打开,我会再次调用recv
猜你喜欢
  • 1970-01-01
  • 2011-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多