I wrote a server-client chat for
Windows (using threads and non-blocking socket), it works fine with single server but still not supports a few clients. Server works like echo (but only for last connected client). Client.c uses CreateThread function and non-blocking sockets.
I made 3 functions to keep socket values of connected clients in the list, print them and remove when client has left. It works fine:
struct listElement
{
SOCKET socket;
struct listElement *next;
};
struct clientList
{
struct listElement* head;
};
int pushBackClient(struct clientList *list, SOCKET socket)
void print(struct clientList *list)
int removeFromList(struct clientList *list, SOCKET socket)
Well, this part is done. Now I can collect sockets of every connected client, when client has disconnected its socket is also removed.
But there is still no multiclient support. How should I realise that? I think my code is needed to change a few strings to reach my porpose. And the next question follows from the last: how should orginize my server to send echo-message to ALL the clients except the client who has sent the message?
What I have tried:
server.c
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;
}
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));
}
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);
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);
}
}
}
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