Использование сокетов для чтения со стороны клиента - PullRequest
0 голосов
/ 03 марта 2010

У меня в основном настроен сервер, и я принимаю новых клиентов (UNIX), и я использую команду select (), чтобы дождаться активности в дескрипторе файла, но я не уверен, как писать со стороны клиентов изатем прочитайте его на стороне сервера

FD_ZERO(&readfds);
FD_SET(server_sockfd, &readfds);
FD_SET(STDIN_FILENO, &readfds); 
while (1) {
   testfds = readfds;
   select(4 + MAXCLIENTS, &testfds, NULL, NULL, NULL);
   for (fd = 0; fd < 4 + MAX_CLIENTS; fd++) {
     if (FD_ISSET(fd, &testfds)) {
        if (fd == server_sockfd) { /* new connection request */
           client_sockfd = accept(server_sockfd, NULL, NULL);
           if (num_clients < MAXCLIENTS) {
              FD_SET(client_sockfd, &readfds);
              num_clients++;
           } else {
              sprintf(message, "XSorry, too many clients.  Try again later.\n");
              write(client_sockfd, message, strlen(message));
              close(client_sockfd);
           }
        } else if (fd == STDIN_FILENO) { 
           fgets(kb_message, BUFSIZ + 1, stdin);
           if (strcmp(kb_message, "quit\n") == 0) {
              sprintf(message, "XServer is shutting down.\n");
              for (fd2 = 4; fd2 < 4 + MAX_CLIENTS; fd2++) {
                 if (FD_ISSET(fd2, &readfds)) {
                    write(fd2, message, strlen(message));
                    close(fd2);
                 }
              }
              close(server_sockfd);
              exit(EXIT_SUCCESS);
           } else {
              sprintf(message, "M%s", kb_message);
              for (fd2 = 4; fd2 < 4 + MAX_CLIENTS; fd2++)
                 if (FD_ISSET(fd2, &readfds))
                    write(fd2, message, strlen(message));
           }
        } else { /* client leaving */
           close(fd);
           FD_CLR(fd, &readfds);
           num_clients--;
        }
     }
  }

}

Как бы я обработал запрос на запись от клиентов, а затем выполнил бы обратную запись для них, будет ли он в разделе «еще» и как я могу проверитьесли клиент выходит или пишет.

Спасибо

Ответы [ 4 ]

2 голосов
/ 03 марта 2010

Самая распространенная ошибка с select(2) - , не повторная инициализация наборов дескрипторов , поскольку второй, третий и четвертый аргументы - параметры ввода-вывода .

Установите fd_set, для чтения перед внешним циклом, добавьте к нему дескриптор сокета прослушивания, введите цикл, сделайте копию этого fd_set и передайте копию select(2) , Когда появится новое соединение, добавьте его дескриптор к оригинал fd_set. То же самое для закрытого сокета (ошибка или EOF на read(2)) - удалите дескриптор из оригинал fd_set.

Надеюсь, это поможет.

1 голос
/ 03 марта 2010

Вы правы, считая, что вам нужен код чтения в вашем блоке 'else'. Если дескриптор файла срабатывает, а это не stdin или дескриптор 'connect', то это один из ваших клиентов, пытающихся отправить вам данные. Когда один из этих файловых дескрипторов запускается в select, вам нужно вызвать read для этого дескриптора, чтобы прочитать данные в буфер. Команда чтения вернет вам количество прочитанных байтов. Если это положительное число, это означает, что клиент отправил вам данные. Если он равен нулю, это означает, что клиент завершил TCP-соединение с вашим сервером.

Блок else будет выглядеть примерно так:

 else 
  {
     //Existing connection has data for us to read
     if((nBytes = read(fd, buffer, MAXBUFFER)) <= 0) 
     {
        if(nBytes == 0)
        {
          //Actually, its sending us zero bytes, connection closed
          printf("Socket %d hung up\n", fd;
        }
     else
          printf ("Read Error"\n)
  }

Кроме того, следуйте советам Николая Н. Фетисова, приведенным выше, и убедитесь, что при подключении клиента вы сохраняете его fd в постоянной структуре fd_set, поскольку та, которую вы используете, изменяется вызовом select.

0 голосов
/ 03 марта 2010
else 
{
  bzero(buf,100);
     n=read(i,buf,100); // Read the client message 
            buf[n]='\0';
       if(n==0) // Check the client is closed or not 
      {

              printf("%d is closed\n",i);
              close(i);
              FD_CLR(i, &master);
              if(i==fdmax)
              fdmax--;

       }
       else
       {
            n=strlen(buf);

        write(1,buf,n);
        fflush(stdout);

          write(1,"Enter the message\n",18);
          bzero(buf,100);
          read(0,buf,100);
            buf[n]='\0';
          write(i,buf,n);
          fflush(stdout);
       }
    } 

Примечания: После принятия клиента, добавьте клиента в набор fd. Затем прочитайте сообщение от клиента Если сообщение равно 0, то клиент закрывается. Если вы хотите отправить сообщение клиенту, используя клиент fd, вы можете отправить клиенту

0 голосов
/ 03 марта 2010

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

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