C++ 从本地工作中恢复,但不要';在执行之间的随机端口上无法接收任何内容
我正在开发一个多线程UDP侦听器,我陷入了一个绝对超越我的问题 因此,我需要在几个端口接收大量UDP数据包。在本地,对我来说,最好的解决方案是调用非阻塞recvfrom,线程数量与我正在侦听的端口数量相同(select和poll对于我的要求来说太慢)。我使用的是线程池管理器,它只调用线程和队列任务。代码如下:C++ 从本地工作中恢复,但不要';在执行之间的随机端口上无法接收任何内容,c++,c,multithreading,sockets,recvfrom,C++,C,Multithreading,Sockets,Recvfrom,我正在开发一个多线程UDP侦听器,我陷入了一个绝对超越我的问题 因此,我需要在几个端口接收大量UDP数据包。在本地,对我来说,最好的解决方案是调用非阻塞recvfrom,线程数量与我正在侦听的端口数量相同(select和poll对于我的要求来说太慢)。我使用的是线程池管理器,它只调用线程和队列任务。代码如下: void receiveFromSocket(void * arguments){ sockaddr_in client; // Local socklen_t cli
void receiveFromSocket(void * arguments){
sockaddr_in client; // Local
socklen_t clientSize = sizeof(client);
memset(&client, 0, sizeof(client));
struct arg_struct_listenPort *args2 = (struct arg_struct_listenPort *)arguments;
int fd = args2->arg_fd;
int port = args2->arg_port;
for(;;) {
char buf[158];
memset(buf,0,158*sizeof(char));
int n = recvfrom(fd, (char * ) buf, 158, MSG_DONTWAIT, ( struct sockaddr *) &client, &clientSize);
if(n == -1){
//cerr << "Error while receiving from client: " << errno << endl;
continue;
}
if(n != 158){
cerr << "Discarded message since it's not 158 bytes." << endl;
continue;
}
struct arg_struct args;
args.arg_port = port;
memcpy(args.buf,buf,158);
thpool_add_work(globals.thpool, socketThread, (void*)(&args));
}
}
/// Runs the Socket listener
int network_accept_any()
{
vector<int>::iterator i;
for(i = globals.fds.begin(); i != globals.fds.end(); i++){
int port = distance(globals.fds.begin(),i);
struct arg_struct_listenPort args;
args.arg_fd = *i;
args.arg_port = globals.cmnSystemCatalogs[port].diag_port;
thpool_add_work(globals.thpool, receiveFromSocket, (void*)(&args));
}
cout << "Listening threads created..." << endl;
return 0;
}
void receiveFromSocket(void*参数){
客户端中的sockaddr_;//本地
socklen_t clientSize=sizeof(客户端);
memset(&client,0,sizeof(client));
struct arg_struct_listenPort*args2=(struct arg_struct_listenPort*)参数;
int fd=args2->arg\u fd;
int端口=args2->arg\u端口;
对于(;;){
char-buf[158];
memset(buf,0158*sizeof(char));
int n=recvfrom(fd,(char*)buf,158,MSG_DONTWAIT,(struct sockaddr*)和clientSize);
如果(n==-1){
//cerr多么令人惊讶的欢迎
@molbdnilo是绝对正确的:
您正在使用指向其生存期已结束的对象的指针(&args)。
这有未定义的行为-它可能看起来有效,但它是一个bug
那需要一个修理工
这是固定的代码。向线程提供参数时要小心
void receiveFromSocket(void * arguments){
sockaddr_in client; // Local
socklen_t clientSize = sizeof(client);
memset(&client, 0, sizeof(client));
struct arg_struct_listenPort *args2 = (struct arg_struct_listenPort *)arguments;
int fd = args2->arg_fd;
int port = args2->arg_port;
for(;;) {
char buf[158];
memset(buf,0,158*sizeof(char));
int n = recvfrom(fd, (char * ) buf, 158, MSG_WAITALL, ( struct sockaddr *) &client, &clientSize);
if(n == -1){
cerr << "Error while receiving from client: " << errno << endl;
continue;
}
if(n != 158){
cerr << "Discarded message since it's not 158 bytes." << endl;
continue;
}
arg_struct *args = new arg_struct;
args->arg_port = port;
memcpy(args->buf,buf,158);
thpool_add_work(globals.thpool, socketThread, (void*)(args));
}
}
/// Runs the Socket listener
int network_accept_any()
{
vector<int>::iterator i;
for(i = globals.fds.begin(); i != globals.fds.end(); i++){
int port = distance(globals.fds.begin(),i);
arg_struct_listenPort *args = new arg_struct_listenPort;
args->arg_fd = *i;
args->arg_port = globals.cmnSystemCatalogs[port].diag_port;
thpool_add_work(globals.thpool, receiveFromSocket, (void*)(args));
}
cout << "Listening threads created..." << endl;
return 0;
}
void receiveFromSocket(void*参数){
客户端中的sockaddr_;//本地
socklen_t clientSize=sizeof(客户端);
memset(&client,0,sizeof(client));
struct arg_struct_listenPort*args2=(struct arg_struct_listenPort*)参数;
int fd=args2->arg\u fd;
int端口=args2->arg\u端口;
对于(;;){
char-buf[158];
memset(buf,0158*sizeof(char));
int n=recvfrom(fd,(char*)buf,158,MSG_WAITALL,(struct sockaddr*)和clientSize);
如果(n==-1){
cerr语言注释:通过IP网络的数据单元称为“数据包”,而不是“数据包”。如果您将尽可能多的线程用于该任务,那么执行非阻塞I/O在最好的情况下似乎是无用的。在最坏的情况下,这可能会导致您的问题,因为您将有很多繁忙的循环。通常,这是多线程和非阻塞I/O之间的选择。此外,每个端口一个线程,池可能会起作用没有什么有用的。在每个端口用一个线程执行阻塞I/O是我将多线程应用于此类任务的方式。谢谢你的评论,John。我理解你的意思。但是我以很高的速度接收数据包,使用阻塞I/O使我多次接收相同的数据包。无论如何,它应该能够接收到相同的数据包每个端口至少有一个数据包,对吗?UDP,顾名思义是不保证的。不管你做什么,你都不能保证发送的数据包会被传递。此外,如果“使用阻塞I/O使我多次接收相同的数据包”,这表明你的代码中有一个bug。默认设置中没有任何固有的缺陷“阻止I/O”最终会复制数据包。您只需调试自己的代码。“您使用的是指向生命周期已结束的对象的指针(&args
)。这有未定义的行为-它可能看起来有效,但这是一个需要修复的错误。”。
void receiveFromSocket(void * arguments){
sockaddr_in client; // Local
socklen_t clientSize = sizeof(client);
memset(&client, 0, sizeof(client));
struct arg_struct_listenPort *args2 = (struct arg_struct_listenPort *)arguments;
int fd = args2->arg_fd;
int port = args2->arg_port;
for(;;) {
char buf[158];
memset(buf,0,158*sizeof(char));
int n = recvfrom(fd, (char * ) buf, 158, MSG_WAITALL, ( struct sockaddr *) &client, &clientSize);
if(n == -1){
cerr << "Error while receiving from client: " << errno << endl;
continue;
}
if(n != 158){
cerr << "Discarded message since it's not 158 bytes." << endl;
continue;
}
arg_struct *args = new arg_struct;
args->arg_port = port;
memcpy(args->buf,buf,158);
thpool_add_work(globals.thpool, socketThread, (void*)(args));
}
}
/// Runs the Socket listener
int network_accept_any()
{
vector<int>::iterator i;
for(i = globals.fds.begin(); i != globals.fds.end(); i++){
int port = distance(globals.fds.begin(),i);
arg_struct_listenPort *args = new arg_struct_listenPort;
args->arg_fd = *i;
args->arg_port = globals.cmnSystemCatalogs[port].diag_port;
thpool_add_work(globals.thpool, receiveFromSocket, (void*)(args));
}
cout << "Listening threads created..." << endl;
return 0;
}