繁体   English   中英

一段时间后,写入操作始终为连接的非阻塞套接字返回EAGAIN

[英]write always returns EAGAIN for connected nonblock socket after a while

我在ubuntu linux盒子上用c编写客户端服务器套接字程序。 服务器端需要处理许多连接,服务器和客户端都具有本地套接字,以便在对其进行一些操作之后将接收到的数据发送到本地进程,并且发送和接收的数据数量巨大。 (数据大小不是很大,最大为1500)是下面的图:
[客户端的本地进程] <->数据<->客户端<--------->服务器<->数据<-> [服务器的本地进程]

因此所有套接字(client_local_socket,client_remote_socket,server_remote_socket,server_local_socket)都必须是非阻塞的。

当我在局域网中的两台计算机上运行客户端和服务器时,它可以正常工作,但是当将服务器程序移至Internet中的linux服务器(客户端连接到nat后面的服务器)时,客户端开始与服务器成功通信(两个客户端)和服务器收到一些EAGAIN错误,但在下一次尝试后恢复,并且我知道它对于非阻塞来说非常正常),但过了一会儿(超过1000个发送和接收数据包),client_remote_socket写入错误代码EAGAIN失败,并且无法在下一次尝试中恢复它,然后,它总是得到该死的EAGAIN进行写入。 顺便说一句client_remote_socket在读取时没有问题,并且始终从服务器获取数据包。 服务器完全没有问题,client_local_socket在写入和读取过程中都发挥作用。

我使用以下代码使套接字成为非阻塞的:

int flags;
if ((flags = fcntl(client_remote_socket, F_GETFL, 0)) < 0)
    flags = 0;
flags = flags | O_NONBLOCK;
fcntl(client_remote_socket, F_SETFL, flags);

我也尝试过:

fcntl(client_remote_socket, F_SETFL, O_NONBLOCK);

但是结果是一样的。

我使用的唯一setsockopt是服务器端的SO_REUSEADDR,而客户端没有setsockopt。

值得一提的是,我总是检查write返回的值,当它小于0时,我检查errno并查看其EAGAIN。 据我所知,当内核没有用于写缓冲区的可用空间,并且在具有4 GB内存的笔记本电脑中内核对我没有内存时,写操作将返回EAGAIN。 当我在局域网中同时运行客户端和服务器时,BTW可以正常工作。 当这种情况在客户端中发生时,服务器不会显示客户端套接字损坏的任何迹象,这是正确的,因为与此同时,它可以从服务器接收数据。 我一遍又一遍地检查了代码,并尝试对其进行多次调试,没有发现任何错误。 我还使用了select系统调用来检查套接字是否可用于写入,并且当时间到来时总是返回0。 现在我不知道要解决这个问题,任何想法对我来说都会非常感激。 谢谢。

上周我遇到了同样的问题,经过研究后,我发现这是因为对等方的缓冲区已满。 我测试了这种情况。

当远程缓冲区已满时,它告诉您的本地堆栈停止发送。 当从远程缓冲区中清除数据(通过由远程应用程序读取)时,远程系统将通知本地系统发送更多数据。

这是布莱恩·怀特的答案https://stackoverflow.com/a/14244450/3728361

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM