C, программирование сокетов: подключение нескольких клиентов к серверу с помощью select ()

Я пытаюсь создать сервер, к которому можно подключить несколько клиентов. Вот мой код:

Клиент:

int main(int argc, char **argv) { struct sockaddr_in servaddr; int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock == -1) perror("Socket"); bzero((void *) &servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(6782); servaddr.sin_addr.s_addr = inet_addr(); if (-1 == connect(sock, (struct sockaddr *)&servaddr, sizeof(servaddr))) perror("Connect"); while(1) { char message[6]; fgets(message, 6, stdin); message[5] = '\0'; send(sock, message, 6, 0); } close(sock); } 

Сервер:

 int main(int argc, char **argv) { fd_set fds, readfds; int i, clientaddrlen; int clientsock[2], rc, numsocks = 0, maxsocks = 2; int serversock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (serversock == -1) perror("Socket"); struct sockaddr_in serveraddr, clientaddr; bzero(&serveraddr, sizeof(struct sockaddr_in)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons(6782); if (-1 == bind(serversock, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr_in))) perror("Bind"); if (-1 == listen(serversock, SOMAXCONN)) perror("Listen"); FD_ZERO(&fds); FD_SET(serversock, &fds); while(1) { readfds = fds; rc = select(FD_SETSIZE, &readfds, NULL, NULL, NULL); if (rc == -1) { perror("Select"); break; } for (i = 0; i < FD_SETSIZE; i++) { if (FD_ISSET(i, &readfds)) { if (i == serversock) { if (numsocks  0) { index += in; limit -= in; } printf("%d\n", index); printf("%s\n", message); } } } } close(serversock); return 0; } 

Как только клиент подключается и отправляет свое первое сообщение, сервер просто запускается в бесконечном цикле и выплескивает мусор из массива сообщений. Кажется, что recv ничего не получает. Может ли кто-нибудь увидеть, где я ошибаюсь?

    В вашем коде две проблемы:

    • Вы должны сделать recv(i, ...) вместо recv(clientsock[i], ...)

    • После этого вы не проверяете, не recv() ли recv() , и поэтому printf() выводит неинициализированное буферное message , поэтому мусор на выходе

    Вам нужно проверить ограничение <= 0 в вашем цикле чтения, прежде чем вы вызовете чтение.

    В цикле while для сервера измените код, чтобы сделать recv(i) вместо recv(clientsocks[i]) . Я реализовал этот код и работает с этим изменением.

    Я заменил другое ниже, и он работает

      } else { /* int messageLength = 5; char message[messageLength+1]; int in, index = 0, limit = messageLength+1; memset ( &message[index] , 0, sizeof ( message [index] ) ); while ((in = recv(i, &message[index], limit, 0)) > 0) { index += in; limit -= in; } printf("%d\n", index); printf("%s\n", message); */ bzero(buf, sizeof(buf)); if ((rval = read(i, buf, 1024)) < 0) perror("reading stream message"); else if (rval == 0) printf("Ending connection\n"); else printf("-->%s\n", buf); } 

    1) Рекомендуется использовать PF_INET (семейство протоколов), а не
    AF_INET (семейство адресов) во время создания Socket.

    2) в пределах цикла while (1)
    каждый раз рекомендуется сделать ваши readfds пустыми, используя FD_ZERO (& readfds). в вызове recv () вы должны использовать i, а не clientsocks [i] вы должны проверить, что возвращаемое значение recv отрицательно (что указывает на ошибку при чтении), если это так, что вам не нужно печатать сообщение. во время печати сообщения убедитесь, что stdout / server готов для записи чего-либо, что вы можете сделать, используя writefds (третий аргумент select).