【问题标题】:C socket - not all socket receive in select()C 套接字 - 并非所有套接字都在 select() 中接收
【发布时间】:2014-06-05 13:04:01
【问题描述】:

我的多线程项目有一个问题:我创建了一些线程,这些线程必须相互发送和接收 udp 消息,因此每个线程都在使用 select() 侦听多个套接字。问题是:只有最后一个套接字插入到 fd_set 变量中,才能接收消息。不知道为什么

这是代码:

线程的初始部分:

int                     fdmax;
fd_set                  read_fd_set, service_fd_set;
/* allocate memory for receive msg */
msg=malloc(sizeof(char)*(SIZEBUF));

FD_ZERO(&read_fd_set);
FD_ZERO(&service_fd_set);

fdmax=0;

if (param->n_port != 0){

    for (x=0; x<(param->n_port); x++){
        /* take the port from array */
        local_port_number = param->l_port_in[x];
        /* create socket udp and bind on localhost */
        socketfd=create_socket(local_port_number);
        /* save socket_fd in my data struct */   
        param->sock_fd_local[x]=socketfd;
        /* add socket in fd_set */
        FD_SET(socketfd,&service_fd_set);

        if (socketfd > (fdmax-1)){
            fdmax=socketfd + 1;
        }

线程的第二部分:

for(;;){

    read_fd_set=service_fd_set;

    ris=select(fdmax,&read_fd_set,NULL,NULL,NULL);

    if(ris<0){
        if (errno!=EINTR){
            printf(_KRED "Error in select: errno different from EINTR \n" _KNRM);
        }
    }
    if (ris>0){

        for(p=0; p<fdmax; p++){

            if((FD_ISSET(p,&read_fd_set))!=0){
                for( x=1; x<=5; x++){
                    if( p == param->sock_fd_local[x]){

                        /* setup datagram to receive */
                        memset(&From, 0, sizeof(From));
                        Fromlen=sizeof(struct sockaddr_in);

                        /* RECVFROM */
                        msglen = recvfrom ( p, msg, (int)SIZEBUF, 0, (struct sockaddr*)&From, &Fromlen);
                        if (msglen<0){
                            ...
                        }else{
                            sprintf((char*)string_remote_ip_address,"%s",inet_ntoa(From.sin_addr));
                            remote_port_number = ntohs(From.sin_port);
                            print_msg(...);

                        }
                    }
                }
            }
        }
    }                                                       

}       

谁能帮帮我?

整个项目在这里:https://github.com/bonfi/SpanningTreeUDP

(对不起我的英语,我是意大利人,该项目是用意大利语评论的)

【问题讨论】:

  • 这里不是所有人都懂意大利语,我建议在google上翻译并发表评论,让用户理解并帮助你。

标签: c sockets select udp


【解决方案1】:

我相信至少有一个,如果不是两个的话。第一个在第二部分,在 recvfrom 函数中,您正在使用 socketfd 但未将其设置为您要从中接收数据的套接字。变量 socketfd 包含您从初始代码创建的最后一个套接字。我怀疑这就是为什么您只从一个线程获取数据的原因,该线程是最后一个创建的套接字。

我不太了解的另一项是 if 语句之后的循环,第二部分中带有 FD_ISSET。我不确定你为什么用 x 循环然后设置 p 或者你为什么要做 4 次。

我建议第二部分的代码应该如下所示,从 FD_ISSET if 语句开始。

        if((FD_ISSET(p,&read_fd_set))!=0){
            socketfd == param->sock_fd_local[p]){

            /* setup datagram to receive */
            memset(&From, 0, sizeof(From));
            Fromlen=sizeof(struct sockaddr_in);

            /* RECVFROM */
            msglen = recvfrom ( socketfd, msg, (int)SIZEBUF, 0, (struct sockaddr*)&From, &Fromlen);
            if (msglen<0){
                ...
            }else{
                 sprintf((char*)string_remote_ip_address,"%s",inet_ntoa(From.sin_addr));
                 remote_port_number = ntohs(From.sin_port);
                 print_msg(...);

            }
        }

我删除了带有 x 变量的 for 循环,并使用 p 来索引结构,以根据 FD_ISSET 是否返回 true 来设置用于接收数据的 socketfd。这样,您将根据文件描述符设置 socketfd 变量(如果已设置)。

【讨论】:

  • 谢谢!你有理由,问题出在recvrom(socketfd,..):我已经解决了在recvfrom中使用p代替socketfd。
  • FD_ISSET之后的循环是因为我必须模拟Lan(一个线程foreach)和Bridge(相同,1个线程),所以一个线程/Lan最多可以连接5个Bridge(具体我的项目); param->n_port 表示到网桥的链接/连接数。所以在选择之后我必须查看我在哪个连接中接收数据包。 for 循环不正确:您说循环 4 次,我更改为“for(x=0;x
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多