У меня есть вопрос, когда я использую read () в select - PullRequest
0 голосов
/ 03 апреля 2011

У меня есть вопрос, когда я использую select () и read ().коды клавиш: Свернуть

nready = select( maxfd + 1, server->fd_readset, 0, 0, timeout );
       if( nready > 0 )
               printf( "nready is %d\n", nready );

       char buf[100];
       int n ;
       if ( FD_ISSET( server->fd , server->fd_readset ) )    /* new client connection */
       {
               int s = (int)accept( server->fd, 0, 0 );
               if ( s == -1 )
               {
                       printf( " errno is %d\n", errno );
                       fprintf( stdout, "error is %s\n", strerror( errno ) );
               }
               printf( "s is %d\n", s );
               for ( j = 0; j < FD_SETSIZE; j++ )
               {
                       if ( client[j] < 0 )
                       {
                               if( s > 0 )
                                       client[j] = s;  /* save descriptor */
                               break;
                       }
                }

        if ( j == FD_SETSIZE )
        {
                printf( "too much clients!\n" );
        }
        FD_SET( s, server->fd_set );    /* add new descriptor to set */
        if( s > maxfd )
                maxfd = s;      /* for select */
        if( j > maxi )
                maxi = j;       /* max index in client[] array */
        if( --nready <= 0 )
                continue;
}
for( j = 0; j <= maxi; j++ )
{
        if( ( sockfd = client[j] ) < 0 )
                continue;
        if( FD_SET( sockfd, server->fd_readset ) )
        {
                if( ( n = read( sockfd, buf, 100) ) != 0 )
                {

Вопрос: я запускаю сервер, но я просто позволяю только одному клиенту отправлять сообщения на сервер функцией write ().другой клиент не может отправлять сообщения.у меня отладка по GDB, я обнаружил, что сервер блокируется в read ();сервер все еще читает первый клиент.я пытаюсь использовать alarm () для ее решения, но это не работает. Когда read () делает тайм-аут, он все еще блокируется.Пожалуйста, скажи мне почему?спасибо.

Ответы [ 3 ]

2 голосов
/ 03 апреля 2011

if( FD_SET( sockfd, server->fd_readset ) )

Эта строка устанавливает дескриптор в читаемом наборе. Вместо этого используйте FD_ISSET для проверки.

1 голос
/ 03 апреля 2011

Возможно, проблема в том, что вы не установили сокет в неблокирующий режим чтения. Ваше чтение будет ждать, пока не появятся все 100 символов, что, вероятно, не то, что вы ожидаете. Если клиент отправляет на сервер 32 байта, сервер будет ожидать чтения, пока не поступит еще 68 байтов.

Проблема еще сложнее. Если вы находитесь в неблокирующем режиме, вы можете получить частичное чтение. Например, клиент может отправить 32 байта на сервер, но сервер может получить только 10 в первом чтении. Сервер должен быть достаточно умным, чтобы знать, что получено частичное сообщение, и ждать следующих 22 байтов.

Лучший способ справиться с select и сокетами - это обеспечить неблокирование всех файловых дескрипторов как для чтения, так и для записи. Это немного усложняет ситуацию.

0 голосов
/ 03 апреля 2011

При использовании select() вы должны пометить все файловые дескрипторы как неблокирующие.

if (fcntl(s, F_SETFL, fcntl(s, F_GETFL, 0) | O_NONBLOCK) == -1) {
  perror("set socket nonblocking");
  exit(1);
}

Вы также должны следить за тем, чтобы read() возвращал -1 с errno, равным EAGAIN, что означает, что фактические данные недоступны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...