相关疑难解决方法(0)

recv()不会被多线程环境中的信号中断

我有一个阻塞recv()循环的线程,我想终止(假设这不能改为select()或任何其他异步方法).

我还有一个捕获的信号处理程序,SIGINT理论上它应该recv()返回错误并errno设置为EINTR.

但它没有,我认为这与应用程序是多线程的事实有关.还有另一个线程,同时在等待pthread_join()通话.

这里发生了什么事?

编辑:

好的,现在我recv()通过pthread_kill()主线程明确地将信号传递给所有阻塞线程(这导致SIGINT安装了相同的全局信号处理程序,尽管多次调用是良性的).但recv()呼叫仍然没有被阻止.

编辑:

我编写了一个代码示例来重现问题.

  1. 主线程将套接字连接到不会让连接进入的行为不当的远程主机.
  2. 所有信号都被封锁
  3. 读线程线程已启动.
  4. 主要解锁和安装处理程序SIGINT.
  5. 读线程解锁并安装处理程序SIGUSR1.
  6. 主线程的信号处理程序将a发送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 sockets linux signals pthreads

17
推荐指数
2
解决办法
1万
查看次数

C套接字可以在没有客户端关闭连接的情况下收集0个字节吗?

我在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个字节,从而导致我的代码过早地退出循环?手册页含糊不清.

c sockets recv server

5
推荐指数
1
解决办法
4602
查看次数

为posix recv设置超时会导致udp数据包丢失吗?

我找到了关于如何设置 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 文档中的引用:

SO_RCVTIMEO
Run Code Online (Sandbox Code Playgroud)

设置超时值,该值指定输入函数完成之前等待的最长时间。它接受一个 timeval 结构,其中包含秒数和微秒数,指定等待输入操作完成的时间限制。如果接收操作已经阻塞了这么长时间而没有接收到额外的数据,则如果没有接收到数据,它将返回部分计数或设置为 [EAGAIN] 或 [EWOULDBLOCK] 的 errno。该选项的默认值为零,这表示接收操作不应超时。该选项采用 timeval 结构。请注意,并非所有实现都允许设置此选项。

我不明白的是:这会导致udp包丢失吗?如果收到udp包超时怎么办?

另相关:为 UDP 套接字的 recv fcn 设置超时

PS:我知道UDP本质上是不可靠的,所以我的问题实际上主要是关于处理UDP消息时发生超时的情况。

c++ sockets posix

2
推荐指数
1
解决办法
1287
查看次数

仅为recv设置超时

我目前正在项目中使用套接字,我想在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()函数?如果是这样,我该怎么办?

c sockets linux

1
推荐指数
1
解决办法
1889
查看次数

标签 统计

sockets ×4

c ×3

linux ×2

c++ ×1

posix ×1

pthreads ×1

recv ×1

server ×1

signals ×1