c++ - 套接字编程:是什么导致 select() 系统调用在当前线程执行时不返回?
问题描述
我在多套接字应用程序上调用select()时遇到问题。
这是它应该如何工作的。
Writer 写入:[0010]HelloWorld
在套接字上,前 4 个字符始终是表示有效负载大小的数字。
读者应该做到以下几点:
- 调用
select()
以验证给定套接字是否可读,然后是read
前 4 个字符,将 char 更改为 digit 以获取缓冲区的大小,并分配该大小的缓冲区。 - 从套接字复制字符(前 4 个字符之后)并粘贴到缓冲区以进行进一步处理
read
再次输入 4 个字符,这应该会失败,并且在无法读取任何数据时,应用程序应该彻底退出程序。
问题出在第三次select
通话中。select
接下来是read
迭代,每次我们检查select()
套接字的可读性并且一旦验证,我们就继续进行read
. read
虽然套接字是有效的并且几乎整个过程都可以正常工作,但除了预期会失败之前的第 3 步的最后一点之外,我select()
最后一次调用系统调用,它在调用时完全冻结了线程select
。
我在网上找不到任何可以解释这种奇怪现象的资源。为了验证线程没有返回,我在进行系统调用之前创建了一个虚拟对象select()
并将其记录在销毁中。不幸的是,破坏者永远不会被调用。
源代码是专有的,不能共享。
片段:
fd_set f_set;
int err = 0;
while(check_edge_case())
{
if(time_out_valid())
{
int nfds = GetFileDescriptor();
FD_ZERO(&f_set);
FD_SET(nfds, &f_set);
for_each (clients, [&](client_t &client)
{
int fd = client.descriptor;
if(fd)
{
FD_SET(fd, &f_set);
nfds = std::max(nfds, fd);
}
});
++nfds;
// perform select
if(time_out_valid())
{
struct timeval_t time_val = GetTimeOut();
err = select(nfds, &f_set, 0,0, &time_val);
}
else
{
err = select(nfds, &f_set, 0, 0, 0); // blocks in this statement
}
// check for error
if(!err)
{
err = 0;
continue;
}
else if (err = -1 && errno == EINTR)
{
err = 0;
continue;
}
else if (err < 0)
{
retunr errno;
}
if(FD_ISSET(GetFileDescriptor(), &f_set))
{
return ECANCELED;
}
// further processing for read operation
bool executed = false;
for_each (clients, [&](client_t &client)
{
int fd = client.descriptor;
if(FD_ISSET(fd, &f_set))
{
if(client.f_read) err = client.f_read();
else err = 0;
executed = true;
break;
}
});
if(!found) return ENODATA;
}
}
解决方案
您将错误的timeout
参数传递给您的第二次调用select
,因此是阻塞的。
从文档中:
如果结构的两个字段
timeval
都为零,则then select()
立即返回。(这对于轮询很有用。)
如果
timeout
指定为NULL
,则select()
无限期地阻塞等待文件描述符准备就绪。
所以传递一个归零timeval
结构的地址,而不是0
,你应该没问题。
推荐阅读
- javascript - 如何让电脑随机选词?
- markdown - Markdown:C++ 是一个有效的锚吗?
- apache-spark - Azure DataBricks Stream foreach 失败并出现 NotSerializableException
- javascript - Vue:offsetTop 总是返回 0
- angular - 自定义 Angular webpack 配置,并非所有选项都能正常工作
- maven - 如何修复maven surefire插件错误[分叉过程中有错误]?
- php - php pdo 执行失败并出现执行错误
- javascript - 如何在Javascript中添加前面带0的数字?
- python - 在 Gurobi Python 中向目标函数添加多个二次项
- excel - 根据一系列条件删除行(复数)