【发布时间】:2014-07-04 12:11:17
【问题描述】:
我正在 ubuntu linux 机器上用 c 语言编写客户端服务器套接字程序。
服务器端需要处理许多连接,并且服务器和客户端都有一个本地套接字,可以在对其进行一些操作后将接收到的数据发送到本地进程,并且发送和接收的数据数量巨大。 (数据量不是很大,最大1500)
这是图表:
[客户端本地进程] 数据 客户端 服务器 数据 [服务器本地进程]
所以所有的套接字(client_local_socket、client_remote_socket、server_remote_socket、server_local_socket)都需要是非阻塞的。
当我在局域网中的两台计算机上运行客户端和服务器时,它可以正常工作,但是当将服务器程序移动到互联网中的 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。
值得一提的是,我总是检查 write 返回的值,当它为
【问题讨论】:
-
我看你别无选择,只能贴出相关代码。
-
不允许套接字使用所有内存,套接字缓冲区有限制,通常最多为几 MB。获取 EAGAIN 是 100% 正常的,这通常意味着网络无法处理更多流量,或者接收应用程序接收速度不够快。
-
让我觉得很奇怪的是,在第一段中,您说“服务器端需要处理许多连接”,而在最后一段中,“我还使用了 select 系统调用”,显然是一种调试机制,而不是作为处理许多连接的必要部分。如果您只是在
send的循环中获得大量的 EGAIN,这不足为奇。 -
谢谢你们帮助我。@Duck 现在,我是唯一连接到服务器的客户端,实时日志显示我可怜的服务器正在等待连接,这是客户端不能发送数据包。得到一堆 EGAIN 对我来说也不足为奇,但问题是,它在几分钟内从不发送任何数据包。我什至已经测试了 15 分钟,但仍然只是 EGAIN :|我使用的选择只返回 0。
-
@nos 我的套接字缓冲区只有 2000 字节,它总是使用最多 1600 或 1700。所以我没有违反 linux 写入缓冲区的大小。网络监控显示没有超出带宽。数据包很小。
标签: c linux sockets nonblocking