简体   繁体   English

C套接字-并非所有套接字都在select()中接收

[英]C socket - not all socket receive in select()

i've a problem wiht my multi-threads project: i create some threads, these must send and receive udp messages with each other, so each thread is listening on multiple sockets with an select(). 我的多线程项目有一个问题:我创建了一些线程,这些线程必须彼此发送和接收udp消息,因此每个线程都使用select()在多个套接字上侦听。 The problem is: only last socket inserted in a fd_set variable, receive messages. 问题是:只有最后一个套接字插入fd_set变量中,才能接收消息。 I don't konw why 我不知道为什么

this is code: 这是代码:

initial part of thread: 线程的初始部分:

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;
        }

secondo part of thread: 线程的第二部分:

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(...);

                        }
                    }
                }
            }
        }
    }                                                       

}       

anyone can help me? 有人可以帮助我吗?

The entire project is here: https://github.com/bonfi/SpanningTreeUDP 整个项目在这里: https : //github.com/bonfi/SpanningTreeUDP

(sorry for my english, i'm italian, the project is commented in italian) (对不起,我的英语,我是意大利语,该项目用意大利语发表了评论)

I believe there are is at least one if not two issues. 我相信至少有一个甚至两个问题。 The first one is in the second part, in the recvfrom function, you are using socketfd but not setting it to the socket from which you want to receive data. 第一个是在第二部分的recvfrom函数中,您正在使用socketfd,但未将其设置为要从中接收数据的套接字。 The variable socketfd contains the last socket you created from the initial code. 变量socketfd包含您从初始代码创建的最后一个套接字。 I suspect that is why you are only getting data from one thread which was the last socket created. 我怀疑这就是为什么您仅从一个线程(它是最后创建的套接字)获取数据的原因。

The other item which I don't quite understand is the loop after the if statement with teh FD_ISSET in the second part. 我不太了解的另一项是第二部分中带FD_ISSET的if语句之后的循环。 I'm not sure why you are looping with x and then setting p or why you are doing 4 times. 我不确定为什么要用x循环然后设置p或为什么要进行4次。

I would propose the code in the second part should look like the follow starting at the FD_ISSET if statement. 我建议第二部分中的代码应类似于以下以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(...);

            }
        }

I removed the for loop with the x variable and I am using p to index the structure to set the socketfd for receiving data based on if the FD_ISSET returns true. 我使用x变量删除了for循环,并使用p来对结构进行索引,以根据FD_ISSET是否返回true来设置用于接收数据的socketfd。 That way you are setting the socketfd variable based on the file descriptor if it is set. 这样,您可以根据文件描述符(如果已设置)来设置socketfd变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM