TCP客户端-服务器SIGPIPE

4

我正在设计和测试一个基于TCP套接字(Internet域)的客户端服务器程序。目前,我正在本地机器上进行测试,但是对SIGPIPE以下内容无法理解。

*. SIGPIPE出现的时机很随机。它是否可以是确定性的?

最初的测试包括从客户端发送单个小型(25个字符)操作,并在服务器上进行相应的接收。同样的代码,在同一台机器上运行成功或不成功(SIGPIPE),完全不受我的控制。失败率约为45%(非常高)。因此,我是否可以通过某种方式调整机器以将其最小化。

**. 第二轮测试是从客户端向服务器发送40000个小型(25个字符)消息(总共1MB的数据),然后服务器响应其实际接收到的数据总大小。客户端在紧密循环中发送数据,并且服务器只有一个接收调用。它仅适用于发送的总数据量最大为1200字节,并且现在存在这些非确定性的SIGPIPE,约占70%(真的很糟糕)。

有人能建议一些改进我的设计吗(可能会在服务器上)。要求是客户端在与服务器建立单个套接字连接后能够发送中到非常高量的数据(每个消息约25个字符)。我有一种感觉,针对单个接收的多个发送将始终有丢失和非常低效的情况。我们应该将消息组合并在一个send()操作中发送。这是唯一的方法吗?

2个回答

9

SIGPIPE是在尝试向未连接的管道/套接字写入数据时发送的信号。安装该信号的处理程序将使send()返回一个错误。

signal(SIGPIPE, SIG_IGN);

另外,您可以为套接字禁用SIGPIPE:

int n = 1;
setsockopt(thesocket, SOL_SOCKET, SO_NOSIGPIPE, &n, sizeof(n));

此外,你提到的数据量并不是很大。很可能存在某个bug导致你的连接意外关闭,从而引发了SIGPIPE错误。


1
请注意,SO_NOSIGPIPE并不是可移植的。请参考这里:https://dev59.com/RHVD5IYBdhLWcg3wDHDm - Craig M. Brandenburg

2

SIGPIPE信号的触发是因为你试图向一个已关闭的套接字(socket)写入数据。这表明可能存在一个bug,因此请检查你的应用程序并尝试首先解决它。

仅仅屏蔽SIGPIPE信号并不是一个好的做法,因为你无法确定信号来自何处,也可能屏蔽其他源的错误。在多线程环境中,信号是一个可怕的解决方案。

在极少数情况下,如果你不能避免这种情况,你可以在发送(send)时屏蔽该信号。如果你在send()/sendto()函数中设置了MSG_NOSIGNAL标志,它将阻止SIGPIPE信号的触发。如果确实触发了此错误,send()函数会返回-1,并将errno设置为EPIPE。简单易懂。详情请参考man send


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