Один сервер для нескольких клиентов (чат) в C
Я написал серверно-клиентский чат для Окна (используя потоки и неблокирующий сокет), он прекрасно работает с одним сервером, но все еще не поддерживает несколько клиентов. Сервер работает как echo (но только для последнего подключенного клиента). Client. c использует функцию CreateThread и неблокирующие сокеты.
Я сделал 3 функции, чтобы сохранить значения сокетов подключенных клиентов в списке, распечатать их и удалить, когда клиент ушел. Это прекрасно работает:
struct listElement { SOCKET socket; struct listElement *next; }; struct clientList { struct listElement* head; }; /*my implementation function, print and remove*/ int pushBackClient(struct clientList *list, SOCKET socket) void print(struct clientList *list) int removeFromList(struct clientList *list, SOCKET socket)
Что ж, эта часть сделана. Теперь я могу собирать сокеты каждого подключенного клиента, когда клиент отключился, его сокет также удаляется.
Но мультиклиентной поддержки по-прежнему нет. Как я должен понять, что? Я думаю, что мой код необходим чтобы изменить несколько строк, чтобы достигнуть моих программ. И следующий вопрос вытекает из последнего: как организовать мой сервер для отправки Эхо-сообщения всем клиентам, кроме клиента, который отправил сообщение?
Что я уже пробовал:
server.c /* before this cycle there are socket(), listen() and bind() functions */ while (1) { FD_ZERO(&readSet); FD_SET(listeningSocket, &readSet); if (newSocketDescriptor) { FD_SET(newSocketDescriptor, &readSet); } tv.tv_sec = 5; retVal = select(listeningSocket + 1, &readSet, NULL, NULL, 0); if (retVal == SOCKET_ERROR) { printf("Select error"); break; } else if (retVal == 0) { printf(". . .\n"); continue; } else { if ((FD_ISSET(listeningSocket, &readSet)) != 0) { if ((newSocketDescriptor = accept(listeningSocket, (struct sockaddr *)&clientAddr, &clientAddrSize)) == SOCKET_ERROR) { printf("Accept error "); break; } /* newSocketDescriptor - new connected client, then implement the list */ pushBackClient(&clientList, newSocketDescriptor); print(&clientList); FD_ZERO(&readSet); FD_SET(newSocketDescriptor, &readSet); nclients++; PRINTUSERS HOSTENT *hst = gethostbyaddr((const char *)&serverAddr.sin_addr.s_addr, 4, AF_INET); printf("Welcome %s (%s:%d) new connected\n", hst->h_name, inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port)); } // READ if (FD_ISSET(newSocketDescriptor, &readSet) != 0) { if ((numBytes = recv(newSocketDescriptor, &bufferData[0], sizeof(bufferData), 0)) == SOCKET_ERROR) { printf("Recv failed\n"); break; } else { if (!strcmp(&bufferData[0], "quit\n")) { removeFromList(&clientList, newSocketDescriptor); // if server gets "quit" - remove socket from the list newSocketDescriptor = 0; nclients--; PRINTUSERS printf("Recv failed\n"); printf("It seems client (%s:%d) has disconnected\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port)); FD_ZERO(&readSet); } else { bufferData[numBytes] = '\0'; Sleep(250); printf("Client -> Server: %s", &bufferData[0]); FD_ZERO(&writeSet); FD_SET(newSocketDescriptor, &writeSet); } } } // WRITE (send) if (FD_ISSET(newSocketDescriptor, &writeSet) != 0) { if (send(newSocketDescriptor, &bufferData[0], strlen(&bufferData[0]), 0) == SOCKET_ERROR) { printf("Send error"); break; } bufferData[numBytes] = '\0'; Sleep(250); printf("Server -> Client: %s", &bufferData[0]); } } } Thanks for attention and advices