gpt4 book ai didi

c++ - 从多个文件描述符异步接收 UDP 数据包

转载 作者:太空宇宙 更新时间:2023-11-04 11:02:17 25 4
gpt4 key购买 nike

我对使用 fcntl 和 sigaction 异步接收 UDP 数据包有疑问。在我的程序中,我有两个想要监视的 UDP 流量源。我已经为流量设置了两个套接字并使用了this设置文件描述符以在我收到 UDP 数据包时触发 sigaction 的教程。

这只适用于一个源,但是当我添加另一个源时,只要任一文件描述符接收到数据包,它就会只触发一个处理程序。

这是一个演示行为的简短程序:

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int done;
int a_fd;
int b_fd;

int recv_dgram(int fd, char* dgram, int size)
{
struct sockaddr_in addr;
int fromlen = sizeof(addr);
return recvfrom(fd, dgram, size, 0, (struct sockaddr*)&addr, (socklen_t*)&fromlen);
}

void a_handler(int signum)
{
char dgram[256];
int size = recv_dgram(a_fd, dgram, 256);
printf("a recieve size: %d\n", size);
}

void b_handler(int signum)
{
char dgram[256];
int size = recv_dgram(b_fd, dgram, 256);
printf("b recieve size: %d\n", size);
}

void sig_handle(int signum)
{
done = 1;
}

int init_fd(int port, const char* group, const char* interface)
{
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if(fd < 0) {
return -1;
}

int reuse = 1;
if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)) < 0) {
close(fd);
return -1;
}

if(fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
close(fd);
return -1;
}

struct sockaddr_in addr;
memset((char*)&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
if(bind(fd, (struct sockaddr*)&addr, sizeof(addr))) {
close(fd);
return -1;
}

struct ip_mreq mcast_group;
mcast_group.imr_multiaddr.s_addr = inet_addr(group);
mcast_group.imr_interface.s_addr = inet_addr(interface);
if(setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mcast_group, sizeof(mcast_group))) {
close(fd);
return -1;
}

return fd;
}

int main(int argc, const char* argv[])
{
done = 0;
signal(SIGINT, sig_handle);
signal(SIGTERM, sig_handle);

// make sockets and sigactions
a_fd = init_fd([a port], [a multicast group], [a interface]);
if(a_fd < 0) {
return -1;
}

pid_t pid = getpid();

int a_flags = fcntl(a_fd, F_GETFL);
fcntl(a_fd, F_SETFL, a_flags | O_ASYNC);

struct sigaction a_sa;
a_sa.sa_flags = 0;
a_sa.sa_handler = a_handler;
sigemptyset(&a_sa.sa_mask);

sigaction(SIGIO, &a_sa, NULL);
fcntl(a_fd, F_SETOWN, pid);
fcntl(a_fd, F_SETSIG, SIGIO);

b_fd = init_fd([b port], [b multicast group], [b interface]);
if(b_fd < 0) {
close(a_fd);
return -1;
}

int b_flags = fcntl(b_fd, F_GETFL);
fcntl(b_fd, F_SETFL, b_flags | O_ASYNC);

struct sigaction b_sa;
b_sa.sa_flags = 0;
b_sa.sa_handler = b_handler;
sigemptyset(&b_sa.sa_mask);

sigaction(SIGIO, &b_sa, NULL);
fcntl(b_fd, F_SETOWN, pid);
fcntl(b_fd, F_SETSIG, SIGIO);

printf("start\n");
while(!done) { pause(); }
printf("done\n");

close(a_fd);
close(b_fd);
return 0;
}

我可以编译它(你也可以用 gcc 编译):

g++ -c 测试.cpp

g++ -o 测试测试.o

我在 Ubuntu 12.04 LTS 上使用 g++ 4.6.3。

当我使用两个 UDP 数据源运行此程序时,当任一文件描述符都有可用数据包时,b_handler 将被触发。因此,只要 a_handler 应该接收数据包,它就会打印“b received size: -1”。 a_handler 永远不会被调用。

我怀疑这是因为 getpid() 将为它们返回相同的值,因此其中一个 sigaction 处理程序将被覆盖。

有什么方法可以让这两个处理程序彼此独立触发?

感谢您的帮助。

最佳答案

使用两个不同的信号,比如 SIGIO 和 SIGUSR1。

fcntl(descriptor, SETSIG, signal_desired);

关于c++ - 从多个文件描述符异步接收 UDP 数据包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26498287/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com