我有一个阻塞recv()循环的线程,我想终止(假设这不能改为select()或任何其他异步方法).
我还有一个捕获的信号处理程序,SIGINT理论上它应该recv()返回错误并errno设置为EINTR.
但它没有,我认为这与应用程序是多线程的事实有关.还有另一个线程,同时在等待pthread_join()通话.
这里发生了什么事?
编辑:
好的,现在我recv()通过pthread_kill()主线程明确地将信号传递给所有阻塞线程(这导致SIGINT安装了相同的全局信号处理程序,尽管多次调用是良性的).但recv()呼叫仍然没有被阻止.
编辑:
我编写了一个代码示例来重现问题.
SIGINT.SIGUSR1.SIGUSR1到读取线程.有趣的是,如果我取代recv()与sleep()被中断就好了.
PS
或者,您只需打开UDP套接字而不是使用服务器.
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
static void
err(const char *msg)
{ …Run Code Online (Sandbox Code Playgroud) 我在C中实现了一个Web服务器.它调用recv()一个连接的阻塞套接字来接收传入的HTTP请求.Linux手册页recv()在阻塞套接字上说明了以下内容:
如果套接字上没有可用的消息,则接收呼叫等待消息到达...接收呼叫通常返回任何可用的数据,直到请求的数量,而不是等待接收所请求的全部金额.
...
这些调用返回接收的字节数,如果发生错误则返回-1 ...当对等体执行有序关闭时,返回值将为0.
因此,要接收完整请求,我的服务器代码包含以下形式的循环:
int connfd; // accepted connection
int len; // # of received bytes on each recv call
...
while (/* HTTP message received so far has not terminated */) {
len = recv(connfd, ...);
if (len == 0) {
// close connfd, then escape loop
} else if (len < 0) {
// handle error
} else {
// process received bytes
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题:recv()由于网络问题而没有客户端执行有序关闭,是否有可能返回0个字节,从而导致我的代码过早地退出循环?手册页含糊不清.
我找到了关于如何设置 posix 套接字超时的答案。该答案的 linux 部分:
// LINUX
struct timeval tv;
tv.tv_sec = timeout_in_seconds;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
Run Code Online (Sandbox Code Playgroud)
以及 posix 文档中的引用:
Run Code Online (Sandbox Code Playgroud)SO_RCVTIMEO设置超时值,该值指定输入函数完成之前等待的最长时间。它接受一个 timeval 结构,其中包含秒数和微秒数,指定等待输入操作完成的时间限制。如果接收操作已经阻塞了这么长时间而没有接收到额外的数据,则如果没有接收到数据,它将返回部分计数或设置为 [EAGAIN] 或 [EWOULDBLOCK] 的 errno。该选项的默认值为零,这表示接收操作不应超时。该选项采用 timeval 结构。请注意,并非所有实现都允许设置此选项。
我不明白的是:这会导致udp包丢失吗?如果收到udp包超时怎么办?
PS:我知道UDP本质上是不可靠的,所以我的问题实际上主要是关于处理UDP消息时发生超时的情况。
我目前正在项目中使用套接字,我想在recv函数中设置5秒的超时.我在这个问题中发现,setsockopt使用SO_RCVTIMEO选项,应该这样做,但问题是它也会影响accept()函数,我只想要recv()函数超时.以下是我设置超时的方法:
/*Setting timeout for bad headers*/
struct timeval tv;
tv.tv_sec = 5; /* 5 seconds timeout for receiving a request */
tv.tv_usec= 0;
setsockopt(fd, SOL_SOCKET,
SO_RCVTIMEO,(struct timeval *)&tv,
sizeof(struct timeval));
Run Code Online (Sandbox Code Playgroud)
这个想法是,如果客户端发送损坏的标头(例如,消息长度不正确),则线程最多等待5秒钟以丢弃请求.
那么,是否可以仅为recv()函数设置此超时而不影响accept()函数?如果是这样,我该怎么办?