I have a client 1 send some data to the server and I want to the server transfer that data to client 2 instead of client 1. Is there any way to tell the server we have to different client sockets, if client 1 send data don't send back to client 1 but send to client 2?
When the server accept the client 1, I try put in it a list but some reason only count as 1 instead of two when server accept the client 2 this function process the buffer from the client unsigned __stdcall ClientSession(void* data) {
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
int iResult;
int iSendResult;
SOCKET ClientSocket = (SOCKET)data;
do
{
// recv buffer from the client
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0)
{
//iSendResult = send(ClientSocket, recvbuf, iResult, 0);
iSendResult = send_data(ClientSocket, recvbuf, iResult);
if (iSendResult == SOCKET_ERROR)
{
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
//receive from the clients
printf("Message %.*s\n", iResult, recvbuf);
}
else if (iResult == 0)
{
printf("Connection closing... \n");
}
else
{
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
} while (iResult > 0);
//ACCEPT COMING CLIENTS
while (ClientSocket = accept(ListenSocket, (sockaddr*)&ClientSocket, NULL))
{
printf("Accepted");
if (ClientSocket == INVALID_SOCKET)
{
printf("accept failed with errir: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
unsigned threadID;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &ClientSession, (void*)ClientSocket, 0, &threadID);
// try add new clients to a list
list<SOCKET> a;
a.push_back(ClientSocket);
for (SOCKET i : a) {
cout << "Hi I'm\n" << ClientSocket;
cout << "MY SIZE\n" << a.size();
}
}
enter code here
CodePudding user response:
Your current architecture starts a thread for each client:
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &ClientSession, (void*)ClientSocket, 0, &threadID);
and then the main thread keeps a list of all client sockets, in a local variable:
list<SOCKET> a;
a.push_back(ClientSocket);
then, whenever a thread receives, you have it send to itself:
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
iSendResult = send_data(ClientSocket, recvbuf, iResult);
Sorry to just rephrase, but hopefully that lets you see the issue. There's two main approaches to address this:
Keep most of this, make the
list<SOCKET> a;
global, add a mutex around it. Change thesend_data
call to send to all clients in the lista
except itself.Forget the idea of a thread per client. Use non-blocking sockets. Have a mainloop that try to receive from each client and then send to all other clients.
The first approach will look something like:
// lock mutex
for(auto s:a)
{
if (s != ClientSocket)
{
iSendResult = send_data(s, recvbuf, iResult);
// error handling
}
}
// unlock mutex
and
// lock mutex (same one)
a.push_back(ClientSocket);
for (SOCKET i : a) {
cout << "Hi I'm\n" << ClientSocket;
cout << "MY SIZE\n" << a.size();
}
// unlock mutex