写入总是在一段时间后返回连接的非块插槽的EAGAIN

时间:2013-11-03 14:58:11

标签: c linux sockets nonblocking

我正在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写作。 BTW 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。

值得一提的是,我总是检查写入返回的值以及何时返回&lt; 0我检查错误并查看其EAGAIN。 据我所知,当内核没有可用于写入缓冲区的空间时,write会返回EAGAIN,并且在没有4GB内存的笔记本电脑中内核没有任何内存也没有任何意义。当我在局域网中运行客户端和服务器时,它会工作。 当这种情况在客户端中出现时,服务器不会显示任何破坏的客户端套接字的迹象,而且它是正确的,因为在此期间,它可以从服务器接收数据。我一次又一次地检查代码,并尝试多次调试,看不出有什么问题。我还使用select系统调用来检查套接字是否可用于写入,并且在时间到来时它总是返回0。 现在我无法解决这个问题,任何想法都会对我很感激。 谢谢。

1 个答案:

答案 0 :(得分:2)

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

  

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

这是Brian White的回答 https://stackoverflow.com/a/14244450/3728361