【发布时间】:2021-02-15 20:22:23
【问题描述】:
我正在用 C 语言编写自己的 Web 服务器。但我遇到了一个烦人的问题。 我正在等待这样的传入连接:
struct sockaddr_in caddr;
uint32_t caddr_len = sizeof(caddr);
int fd = accept(sfd, (struct sockaddr *)&caddr, &caddr_len);
if(fd < 0) {
err(EXIT_FAILURE, "accept()");
}
当accept() 成功时,我开始接收数据:
errno = 0;
ssize_t r = recv(fd, buf, sizeof(buf), 0);
有时在使用 Firefox 访问时,我没有收到任何数据。
当我将超时设置为 1s 时,errno 设置为 EAGAIN。
当我将超时设置为 5s 时,errno 将不会设置,但我仍然没有收到任何数据r == 0。
是否可以配置套接字,使accept() 仅在有实际数据可用时返回?
注意:我在使用 Chrome 访问时没有遇到这种情况。
编辑:有人建议我应该使用poll()
当我使用poll()时,我遇到了同样的问题:
struct pollfd p[] = {{sfd, POLLIN}};
int r = poll(sfd, 1, 1000);
if(r <= 0) err("poll() -> %d", r);
r == 1,但我仍然有同样的问题,因为这个poll() 只适用于监听套接字。接受时它并没有告诉我是否有实际的有效载荷。
【问题讨论】:
-
我找到了解决方案。
poll()可以同时观察多个fds。所以我使用第一个条目作为监听 fd (sfd)。如果有一些变化,我会打电话给fd = accept(sfd)并将新的fd放入同一个监视列表中。当其中一个新创建的fds发生变化时,我就知道这个fd有数据了。 -
不清楚您如何将超时设置为....,以及您如何知道发生了超时。这就是我们要求Minimal, complete and verifiable 示例的原因。请参阅之前引用的页面,并使用如此完整且可验证的示例编辑您的问题。