第一次使用 select(),也许是一个基本问题?

发布于 2024-09-04 17:59:06 字数 4981 浏览 2 评论 0原文

我已经使用 select() 在该服务器上工作了几天。它的作用是,我有两个客户端数组(一个是“供应商”,另一个是“消费者”),服务器的任务是检查供应商是否有东西要发送给消费者,并且如果是的话,请发送。

服务器的第二部分是,当消费者收到供应商的信息时,他们向发送该信息的同一供应商发送一条确认消息。

当客户端连接时,它会被识别为“未定义”,直到它发送一条带有“供应商”或“消费者”一词的消息(西班牙语,因为我来自那里),此时服务器将其放入正确的客户端数组中。

好吧,服务器做什么在这里并不是很重要。重要的是,我正在用两个不同的“for”循环来完成这两个部分,这就是我遇到问题的地方。当第一个用户(无论是供应商还是消费者)连接到服务器时,服务器会陷入第一个或第二个循环,而不是继续执行。因为这是我第一次使用 select(),所以我可能会遗漏一些东西。你们能给我任何帮助吗?

预先非常感谢。

for(;;)
{
    rset=allset;
    nready=select(maxfd+1,&rset,NULL,NULL,NULL);

    if (FD_ISSET(sockfd, &rset))
    {
        clilen=sizeof(cliente);
        if((connfd=accept(sockfd,(struct sockaddr *)&cliente,&clilen))<0)
        {
            printf("Error");
        }

        IP=inet_ntoa(cliente.sin_addr);
        for(i=0;i<COLA;i++)
        {
            if(indef[i]<0)
            {
                indef[i]=connfd;
                IPind[i]=IP;
                break;
            }
        }

        FD_SET(connfd,&allset);     
        if(connfd > maxfd)
        {
            maxfd=connfd;
        }
        if(i>maxii)
        {
            maxii=i;
        }
        if(--nready<=0)
        {    continue; }
    }// Fin ISSET(sockfd)

    for(i=0;i<=maxii;i++)
    {
        if((sockfd1=indef[i])<0)
        { continue; } //!

        if(FD_ISSET(sockfd1,&rset))
        {
            if((n=read(sockfd1,comp,MAXLINE))==0)
            {
                close(sockfd1);
                FD_CLR(sockfd1,&allset);
                indef[i]=-1;
                printf("Cliente indefinido desconectado \n");
            }
            else
            {
                comp[n]='\0';
                if(strcmp(comp,"suministrador")==0)
                {
                    for(j=0;j<=limite;j++)
                    {
                        if(sumi[j]<0)
                        {
                            IPsum[j]=IPind[i];
                            sumi[j]=indef[i];
                            indef[i]=-1;
                            if(j>maxis)
                            {
                                maxis=j;
                            }
                            break;
                        }
                    }
                }
                else if(strcmp(comp,"consumidor")==0)
                {
                    for(o=0;j<=limite;j++)
                    {
                        if(consum[o]<0)
                        {
                            IPcons[o]=IPind[i];
                            consum[o]=indef[i];
                            indef[o]=-1;
                            if(o>maxic)
                            {
                                maxic=o;
                            }
                            break;
                        }
                    }
                }

                if(--nready <=0)
                {
                    break;
                }
            }
        }
    }//fin bucle for maxii
    for(i=0;i<=maxis;i++)
    {
        if((sockfd2=sumi[i])<0)
        {    continue; }

        if(FD_ISSET(sockfd2,&rset))
        {
            if((n=read(sockfd2,buffer2,MAXLINE))==0)
            {
                close(sockfd2);
                FD_CLR(sockfd2,&allset);
                sumi[i]=-1;
                printf("Suministrador desconectado \n");
            }
            else
            {
                buffer2[n]='\0';
                for(j=0;j<=maxic;j++)
                {
                    if((sockfd3=consum[j])<0)
                    {    continue; }
                    else    
                    {
                        strcpy(final,IPsum[i]);
                        strcat(final,":");
                        strcat(final,buffer2);
                        write(sockfd3,final,sizeof(final));
                        respuesta[i]=1;
                    }
                }
                break; // ?
            }
        }
    }//fin for maxis

    for(i=miniic;i<=maxic;i++)
    {
        if((sockfd4=consum[i])<0)
        {    continue; }

        if(FD_ISSET(sockfd4,&rset))
        {
            if((n=read(sockfd4,buffer3,MAXLINE))==0)
            {
                close(sockfd4);
                FD_CLR(sockfd4,&allset);
                consum[i]=-1;
                printf("Consumidor desconectado \n");
            }
            else
            {
                buffer3[n]='\0';
                IP2=strtok(buffer3,":");
                obj=strtok(NULL,":");
                for(j=0;j<100;j++)
                {
                    if((strcmp(IPsum[j],IP2)==0) && (respuesta[j]==1))
                    {
                        write(sumi[j],obj,sizeof(obj));
                        miniic=i+1;
                        respuesta[j]=0;
                        break;                           
                    }
                }
            }
        }
    }

i've been working for a few days with this server using select(). What it does, is that, i have two arrays of clients (one is "suppliers", and the other is "consumers"), and the mission of the server is to check whether the suppliers have something to send to the consumers, and in case affirmative, send it.

The second part of the server is that, when the consumers have received the suppliers' info, they send a confirmation message to the same suppliers that sent the info.

When a client connects, it gets recognized as "undefined", until it sends a message with the word "supplier" or "consumer" (in Spanish, as i'm from there), when the server puts it in the correct clients array.

Well, what the server does is not very important here. What's important is that, i'm doing both parts with two different "for" loops, and that's where i'm getting the problems. When the first user connects to the server (be it a supplier or a consumer), the server gets stuck in the first or second loop, instead of just continuing its execution. As it's the first time i'm using select(), i may be missing something. Could you guys give me any sort of help?

Thanks a lot in advance.

for(;;)
{
    rset=allset;
    nready=select(maxfd+1,&rset,NULL,NULL,NULL);

    if (FD_ISSET(sockfd, &rset))
    {
        clilen=sizeof(cliente);
        if((connfd=accept(sockfd,(struct sockaddr *)&cliente,&clilen))<0)
        {
            printf("Error");
        }

        IP=inet_ntoa(cliente.sin_addr);
        for(i=0;i<COLA;i++)
        {
            if(indef[i]<0)
            {
                indef[i]=connfd;
                IPind[i]=IP;
                break;
            }
        }

        FD_SET(connfd,&allset);     
        if(connfd > maxfd)
        {
            maxfd=connfd;
        }
        if(i>maxii)
        {
            maxii=i;
        }
        if(--nready<=0)
        {    continue; }
    }// Fin ISSET(sockfd)

    for(i=0;i<=maxii;i++)
    {
        if((sockfd1=indef[i])<0)
        { continue; } //!

        if(FD_ISSET(sockfd1,&rset))
        {
            if((n=read(sockfd1,comp,MAXLINE))==0)
            {
                close(sockfd1);
                FD_CLR(sockfd1,&allset);
                indef[i]=-1;
                printf("Cliente indefinido desconectado \n");
            }
            else
            {
                comp[n]='\0';
                if(strcmp(comp,"suministrador")==0)
                {
                    for(j=0;j<=limite;j++)
                    {
                        if(sumi[j]<0)
                        {
                            IPsum[j]=IPind[i];
                            sumi[j]=indef[i];
                            indef[i]=-1;
                            if(j>maxis)
                            {
                                maxis=j;
                            }
                            break;
                        }
                    }
                }
                else if(strcmp(comp,"consumidor")==0)
                {
                    for(o=0;j<=limite;j++)
                    {
                        if(consum[o]<0)
                        {
                            IPcons[o]=IPind[i];
                            consum[o]=indef[i];
                            indef[o]=-1;
                            if(o>maxic)
                            {
                                maxic=o;
                            }
                            break;
                        }
                    }
                }

                if(--nready <=0)
                {
                    break;
                }
            }
        }
    }//fin bucle for maxii
    for(i=0;i<=maxis;i++)
    {
        if((sockfd2=sumi[i])<0)
        {    continue; }

        if(FD_ISSET(sockfd2,&rset))
        {
            if((n=read(sockfd2,buffer2,MAXLINE))==0)
            {
                close(sockfd2);
                FD_CLR(sockfd2,&allset);
                sumi[i]=-1;
                printf("Suministrador desconectado \n");
            }
            else
            {
                buffer2[n]='\0';
                for(j=0;j<=maxic;j++)
                {
                    if((sockfd3=consum[j])<0)
                    {    continue; }
                    else    
                    {
                        strcpy(final,IPsum[i]);
                        strcat(final,":");
                        strcat(final,buffer2);
                        write(sockfd3,final,sizeof(final));
                        respuesta[i]=1;
                    }
                }
                break; // ?
            }
        }
    }//fin for maxis

    for(i=miniic;i<=maxic;i++)
    {
        if((sockfd4=consum[i])<0)
        {    continue; }

        if(FD_ISSET(sockfd4,&rset))
        {
            if((n=read(sockfd4,buffer3,MAXLINE))==0)
            {
                close(sockfd4);
                FD_CLR(sockfd4,&allset);
                consum[i]=-1;
                printf("Consumidor desconectado \n");
            }
            else
            {
                buffer3[n]='\0';
                IP2=strtok(buffer3,":");
                obj=strtok(NULL,":");
                for(j=0;j<100;j++)
                {
                    if((strcmp(IPsum[j],IP2)==0) && (respuesta[j]==1))
                    {
                        write(sumi[j],obj,sizeof(obj));
                        miniic=i+1;
                        respuesta[j]=0;
                        break;                           
                    }
                }
            }
        }
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

沧桑㈠ 2024-09-11 17:59:06

嗯,我认为你的逻辑完全错误。它应该看起来更像这样(警告,未经测试的伪代码):

for (;;)
{
   // First, set up the fd_sets to specify the sockets we want to be notified about
   fd_set readSet;  FD_CLR(&readSet);
   fd_set writeSet; FD_CLR(&writeSet);
   int maxFD = -1;
   for (int i=0; i<num_consumers; i++)
   {
      if (consumer_sockets[i] > maxFD) maxFD = consumer_sockets[i];
      FD_SET(consumer_sockets[i], &readSet);
      if (consumer_has_data_he_wants_to_send[i]) FD_SET(consumer_sockets[i], &writeSet);
   }
   for (int i=0; i<num_producers; i++)
   {
      if (producer_sockets[i] > maxFD) maxFD = producer_sockets[i];
      FD_SET(producer_sockets[i], &readSet);
      if (producer_has_data_he_wants_to_send[i]) FD_SET(producer_sockets[i], &writeSet);
   }

   // Now we block in select() until something is ready to be handled on a socket
   int selResult = select(maxFD+1, &readSet, &writeSet, NULL, NULL);
   if (selResult < 0) {perror("select"); exit(10);}

   for (int i=0; i<num_consumers; i++)
   {
      if (FD_ISSET(consumer_sockets[i], &readSet)
      {
         // There is some incoming data ready to be read from consumer_socket[i], so recv() it now
         [...]
      }
      if (FD_ISSET(consumer_sockets[i], &writeSet)
      {
         // There is buffer space in consumer_socket[i] to hold more outgoing
         // data for consumer_socket[i], so send() it now
         [...]
      }
   }
   for (int i=0; i<num_producers; i++)
   {
      if (FD_ISSET(&producer_sockets[i], &readSet)
      {
         // There is some data ready to be read from producer_socket[i], so recv() it now
         [...]
      }
      if (FD_ISSET(producer_sockets[i], &writeSet)
      {
         // There is buffer space in producer_socket[i] to hold more outgoing
         // data for producer_socket[i], so send() it now
         [...]
      }
   }
}

请注意,要真正正确执行此操作,您需要将所有套接字设置为非阻塞 I/O 并能够处理部分读取和写入(通过将部分数据存储到与该消费者/生产者关联的本地内存缓冲区中,直到您有足够的数据可以操作),否则您将面临调用 recv() 或 send() 块的风险,这将阻止该事件无法为任何其他消费者或生产者提供服务。理想情况下,您应该阻塞的唯一地方是 select()...所有其他调用都应该是非阻塞的。但如果您想让事情一开始就简单,您也许可以暂时不用使用阻塞 I/O。

Hmm, I think your logic is all wrong. It should look something more like this (warning, untested pseudo-code):

for (;;)
{
   // First, set up the fd_sets to specify the sockets we want to be notified about
   fd_set readSet;  FD_CLR(&readSet);
   fd_set writeSet; FD_CLR(&writeSet);
   int maxFD = -1;
   for (int i=0; i<num_consumers; i++)
   {
      if (consumer_sockets[i] > maxFD) maxFD = consumer_sockets[i];
      FD_SET(consumer_sockets[i], &readSet);
      if (consumer_has_data_he_wants_to_send[i]) FD_SET(consumer_sockets[i], &writeSet);
   }
   for (int i=0; i<num_producers; i++)
   {
      if (producer_sockets[i] > maxFD) maxFD = producer_sockets[i];
      FD_SET(producer_sockets[i], &readSet);
      if (producer_has_data_he_wants_to_send[i]) FD_SET(producer_sockets[i], &writeSet);
   }

   // Now we block in select() until something is ready to be handled on a socket
   int selResult = select(maxFD+1, &readSet, &writeSet, NULL, NULL);
   if (selResult < 0) {perror("select"); exit(10);}

   for (int i=0; i<num_consumers; i++)
   {
      if (FD_ISSET(consumer_sockets[i], &readSet)
      {
         // There is some incoming data ready to be read from consumer_socket[i], so recv() it now
         [...]
      }
      if (FD_ISSET(consumer_sockets[i], &writeSet)
      {
         // There is buffer space in consumer_socket[i] to hold more outgoing
         // data for consumer_socket[i], so send() it now
         [...]
      }
   }
   for (int i=0; i<num_producers; i++)
   {
      if (FD_ISSET(&producer_sockets[i], &readSet)
      {
         // There is some data ready to be read from producer_socket[i], so recv() it now
         [...]
      }
      if (FD_ISSET(producer_sockets[i], &writeSet)
      {
         // There is buffer space in producer_socket[i] to hold more outgoing
         // data for producer_socket[i], so send() it now
         [...]
      }
   }
}

Note that to really do this properly, you'd need to set all of your sockets to non-blocking I/O and be able to handle partial reads and writes (by storing the partial data into a local memory-buffer associated with that consumer/producer, until you have enough data to act on), otherwise you risk having a call to recv() or send() block, which would prevent the event loop from being able to service any of the other consumers or producers. Ideally the only place you should ever block in is select()... every other call should be non-blocking. But if you want to keep things simple to start out with, you may be able to get away with using blocking I/O for a while.

世界等同你 2024-09-11 17:59:06

您可以阅读介绍性教程
查看阻塞连接与非阻塞连接

You might read the introductory tutorial
Look at blocking vs non-blocking connections

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文