在处理了我正在编写的C++程序中的一个非常奇怪的错误后,我决定编写以下测试代码,证实了我的怀疑。在原始程序中,在循环中调用send()和this_thread::sleep_for() (具有任意时间量) 16次会导致发送失败,并返回SIGPIPE信号。然而,在本例中,它在4次之后失败。
我有一台服务器运行在绑定到本地主机的端口25565上。原始程序旨在与此服务器进行通信。我在这段测试代码中使用了相同的连接,因为它不会提前终止连接。
int main()
{
struct sockaddr_in sa;
memset(sa.sin_zero, 0, 8);
sa.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &(sa.sin_addr));
sa.sin_port = htons(25565);
cout << "mark 1" << endl;
int sock = socket(AF_INET, SOCK_STREAM, 0);
connect(sock, (struct sockaddr *) &sa, sizeof(sa));
cout << "mark 2" << endl;
for (int i = 0; i < 16; i++)
{
cout << "mark 3" << endl;
cout << "sent " << send(sock, &i, 1, 0) << " byte" << endl;
cout << "errno == " << errno << endl;
cout << "i == " << i << endl;
this_thread::sleep_for(chrono::milliseconds(2));
}
return 0;
}在GDB中运行它就是我发现它发出SIGPIPE的原因。下面是它的输出:http://pastebin.com/gXg2Y6g1
在另一个测试中,我在一个循环中调用this_thread::sleep_for() 16次,然后调用send()一次。这不会产生相同的错误。它运行起来没有问题。
在另一个测试中,我注释掉了线程休眠行,它一直运行得很好。我在原始程序和上面的测试代码中都做到了这一点。
这些结果让我相信这不是服务器关闭连接的情况,尽管这通常是SIGPIPE的意思(为什么它在没有调用this_thread::sleep_for()的情况下运行得很好?)。
你知道是什么导致了这一切吗?我已经摆弄了一个星期了,一点进展也没有。
发布于 2016-07-01 01:46:01
在我的机器上运行这段代码会打印出3分,正如我所期望的那样。它确实在您的一端运行了几次,这一事实告诉我,您有一个服务器在监听端口25565,而您在这个问题中没有包括这个端口。
您的问题是,您没有测试服务器是否关闭了连接。当它发生时,您的进程将获得一个SIGPIPE。因为您不处理该信号,所以您的进程退出。
您可以执行以下操作来解决此问题:
connect和send的潜在错误。我希望这是因为最小化了程序,但这是值得的mentioning.MSG_NOSIGNAL传递给send。在这两种情况下,send都将在errno设置为EPIPE.-1我是认真的。一个简单的man send和搜索SIGPIPE就会给出这个答案。至于为什么服务器关闭,在不知道它是什么服务器和运行什么协议的情况下,我无法回答这个问题。不,不要在评论中回答这个问题。这与这个问题无关。问题的简单事实是,您正在与之交谈的服务器可能在任何时候关闭连接,并且您的代码必须能够处理这种情况。
https://stackoverflow.com/questions/38128598
复制相似问题