Ste*_*son 6 c sockets select tcp
[之前我曾问过类似的事情.这是一个更有针对性的版本.]
什么可以导致服务器的TCP套接字上的select()调用始终超时而不是"看到"客户端的套接字close()?在客户端,套接字是一个常规的socket() - 创建阻塞套接字,成功连接到服务器并成功传输往返事务.在服务器端,套接字通过accept()调用创建,阻塞,通过fork()传递给子服务器进程,由顶级服务器关闭,并由子服务器进程成功使用最初的交易.当客户端随后关闭套接字时,子服务器的select()调用始终超时(1分钟后),而不是在套接字上指示读取就绪状态.select()调用仅查找read-ready条件:write-ready和exception参数为NULL.
这是简化但逻辑上等效的select() - 在子服务器进程中使用代码:
int one_svc_run(
const int sock,
const unsigned timeout)
{
struct timeval timeo;
fd_set fds;
timeo.tv_sec = timeout;
timeo.tv_usec = 0;
FD_ZERO(&fds);
FD_SET(sock, &fds);
for (;;) {
fd_set readFds = fds;
int status = select(sock+1, &readFds, 0, 0, &timeo);
if (status < 0)
return errno;
if (status == 0)
return ETIMEDOUT;
/* This code not reached when client closes socket */
/* The time-out structure, "timeo", is appropriately reset here */
...
}
...
}
Run Code Online (Sandbox Code Playgroud)
这是客户端事件序列的逻辑等价物(错误处理未显示):
struct sockaddr_in *raddr = ...;
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
(void)bindresvport(sock, (struct sockaddr_in *)0);
connect(sock, (struct sockaddr *)raddr, sizeof(*raddr));
/* Send a message to the server and receive a reply */
(void)close(sock);
Run Code Online (Sandbox Code Playgroud)
从不调用fork(),exec()和system().代码比这复杂得多,但这是相关调用的顺序.
Nagel的算法会导致FIN数据包在close()时不被发送吗?
select()Linux 的调用将修改timeout参数的值。从手册页:
在 Linux 上,select() 修改超时以反映未睡眠的时间量
所以你的timeo意志会归零。当它为零时select会立即返回(大多数情况下返回值为零)。
以下更改可能会有所帮助:
for (;;) {
struct timeval timo = timeo;
fd_set readFds = fds;
int status = select(sock+1, &readFds, 0, 0, &timo);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4419 次 |
| 最近记录: |