在通过 epoll 从客户端应用程序的答案中接收数据时遇到问题。
我做了一个简单的插图代码。省略了最大错误处理逻辑。
简短的上下文描述:
- 客户端应用程序创建 2 个非阻塞套接字(SOCK_NON_BLOCK 传递给套接字而不是通过 fcntl)
- 客户端使用 EPOLLOUT 向事件添加套接字 | EPOLLONESHOT 和调用在每个套接字上连接(非阻塞所以我得到 EINPROGRESS) 客户端等待 epoll_wait 建立连接(等待 EPOLLOUT)
- 连接后 - 发送 1 个数据包请求(为了说明,我使用 example.com 主机向 google.com 服务器发出 HEAD 请求)
- 当发送返回时 epoll 通知过滤器切换到 EPOLLIN
- 客户端等待数据读取(如果不是 EAGAIN)并在读取第一个 block 后关闭套接字(没问题)
问题:
只有一个 socket 得到答复已经到来的通知。
在 tcpdump 中,我看到网络服务器发送了两个答案( 这是 tcpdump,突出显示了服务器的两个答案。所以请求都通过了,答案也来了 http://pastie.org/10504786#59-78,89-109 )
我准备了最简单的示例,其中包含两个硬编码的 google ip(为简单起见,跳过名称解析)。
似乎代码对于发布来说有点庞大,所以这里的例子: http://pastie.org/10504718
这里是编译输出:
% gcc -std=c99 -Wall ./main.c && ./a.out
assigned 4 for 173.194.32.135
assigned 5 for 173.194.32.130
socket 4
write event
data send 35 via 4
socket 5
write event
data send 35 via 5
socket 5
read event
read returned 258 <-- we have answer from first
socket 5
read event
read returned 4294967295
read errno =9 errmesg= Bad file descriptor <--its ok cause we closed fd,but seems its event cached event
一只猫看到建立了 2 个连接,并发送了两个请求,但只为一个套接字触发了读取事件。
无法了解这种行为的情况,套接字配置似乎是独立的。
最佳答案
我真丢人。
错误是错误的事件数据初始化。当切换到 IN 时,我忘记重新分配指针做关联结构。所以所有开关都指向相同的数据。
错误代码
//switching data listen
ev.events = EPOLLIN | EPOLLONESHOT;
epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev);
( http://pastie.org/10504718#83-85 )
应该是
//switching data listen
ev.data.ptr = c;
ev.events = EPOLLIN | EPOLLONESHOT;
epoll_ctl(epfd, EPOLL_CTL_MOD, c->fd, &ev);
关于c - Linux 上带有 epoll 的 Tcp 客户端。 EPOLLIN 事件未因多个连接而上升,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33321756/