Click here to Skip to main content
15,886,799 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Dear all,

I am facing a probelm in order to handle data from multiple client in a mutithreaded windows program where server serves each client with different threads.

Probem here is: server always reads(receive) data in the newly create thread(client), irespective of the client tha has sent the message..

In a scenario where Server, Client1 & Client 2 are there and client 2 has joined recently. In this case any data sent by Client 1 server treats as data is sent from Client 2 & handles in the Client 2 thread.

Help on this will be appriciated..

Thanks in advance..
Posted
Updated 21-Dec-11 2:54am
v2
Comments
Chuck O'Toole 21-Dec-11 8:57am    
Dude, there are lots of ways to screw up client/server communications. Without seeing any of your code, we have no way of knowing which one you chose.
srikantpanda 22-Dec-11 5:57am    
HI,

This is how my server program looks like. Same in the client side i have created 2 threads one is responsible for reading the data where as the other for writing of the data.


#include
#include
#include
#include

#pragma comment(lib, "Ws2_32.lib")

#define MYPORT 3490
#define BACKLOG 10

void clientthread(SOCKET *);

SOCKET sockfd, new_fd;
WSADATA wsaData;

SOCKET arr[BACKLOG];
HANDLE hSem=NULL;

int main(void)
{
struct sockaddr_in my_addr;
struct sockaddr_in their_addr;
int sin_size, thread[10], yes=1, x = BACKLOG;
int thread_hndl_count = 0, thread_hndl_count_wait;

if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
{
fprintf(stderr, "WSAStartup failed.\n");
exit(1);
}

if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("Error in socket creation\n");
exit(1);
}

if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&yes,sizeof(yes)) == -1)
{
printf("Error in socket setting up socket\n");
exit(1);
}

my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(MYPORT);
my_addr.sin_addr.s_addr = INADDR_ANY;
memset(&(my_addr.sin_zero), '\0', 8);

if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
{
printf("Error in socket binding\n");
exit(1);
}

if (listen(sockfd, BACKLOG) == -1)
{
printf("Error in socket listen\n");
exit(1);
}

sin_size = sizeof(struct sockaddr_in);
while(x > 0)
{
if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr,&sin_size)) == -1)
{
printf("Error in socket accept");
}
else
{
printf("Server got connection from %s\n",inet_ntoa(their_addr.sin_addr));
arr[thread_hndl_count] = new_fd;
thread_hndl_count++;
printf("Creating the child thread..%d\n",x);
thread[x] = _beginthread( clientthread, 0, &new_fd );
}
x--;
}
printf("Executing statement next to thread creationing\n");
/*
for(thread_hndl_count_wait = 0; thread_hndl_count >= 0; thread_hndl_count--)
{
printf("Executing For loop next to threading\n");
if(thread[thread_hndl_count] != 0)
{
WaitForSingleObject(thread[thread_hndl_count],INFINITE);
}
}*/
Sleep(INFINITE);
closesocket(sockfd);
return 0;
}

void clientthread(SOCKET *client_fd)
{
int maxm_bytes = 50, numbytes = 0, count;
char *Initial_msg= "Initial server confirmation to new client\n";
char *Rcv_buf= (char *) malloc (50);

if (send((SOCKET)*client_fd, Initial_msg, maxm_bytes , 0) == -1)
{
perror("Error in sending\n");
}
else
{
printf("Initial message successfully sent from server and now waiting to receive from the clients\n");
}

while(1)
{
numbytes = recv(*client_fd, Rcv_buf, maxm_bytes , 0);
if(( numbytes == -1 )|| ( numbytes == 0 ))
{
printf("Some one hung up the socket, %d\n", *client_fd);
for(count= 0; count< BACKLOG; count++)
{
if((arr[count] == *client_fd))
{
arr[count] = 0;
closesocket(*client_fd);
}
printf("Terminating child thread\n");
_endthread();
}
}
else
{
printf("Received data from socket %d is %s\n", *client_fd, Rcv_buf);
for(count= 0; count< BACKLOG; count++)
{
if((arr[count] != 0) && (arr[count] != *client_fd))
{
printf("Data to be sent is %d\n", arr[count]);
if (send(arr[count], Rcv_buf, maxm_bytes , 0) == -1)
{
perror("Error in sending\n");
}
}
}
}
}
}

Ok, you have several errors in your logic. This biggest one is that you are passing the address of new_fd as the argument to the processing thread. The thread does *not* move that variable to a safer place but continues to use it through the pointer (i.e., *client_fd). That means you are continuing to access the actual variable new_fd in the main server thread. When the 2nd client comes along, you overwrite new_fd with the socket info the for 2nd client and create a 2nd thread to process it. Now both threads are pointing to the same new_fd variable which contains the SOCKET for the 2nd client, the 1st client's SOCKET is now lost.

You need to capture any "changable" parameter during the start of the thread. Move it to a variable local in scope to the thread. Of course, this opens up a timing issue in that, while unlikely, it is possible for the client connections to come so fast that you process multiple ones in the main thread, creating threads for each, but the threads do not get a chance to start and capture the "changable" data before the main thread overwrites it. Since "SOCKET" is a single "l-value", you can pass it to the thread rather than a pointer to the SOCKET. That would remove the timing issue for l-value type arguments.

Lastly, you have this variable 'x' which you are using as an index into an array of thread ids. 'x' starts at 10 and is decremented after storing each entry. Yet the array is only 10 long so the very first thread you creates exceeds the array boundaries (0..9).
 
Share this answer
 
Comments
Albert Holguin 22-Dec-11 13:08pm    
without looking at his code (since it looks painful to look at as a comment), that looks like it would cause the problems he's seeing... +5
srikantpanda 22-Dec-11 23:29pm    
Thanks Albert for quick revert..

I rewrote the rectifed the logical error u have indicatedin my code & just wonderful it worked..

Thanks once again.
Albert Holguin 23-Dec-11 6:04am    
Chuck did the real work here, so we should be thanking him... ;) ....thanks chuck, :)
srikantpanda 23-Dec-11 6:35am    
yeah how i can forget Chuk..he is just awesome....:):)

Are they all on the same socket? ...if so, that's probably why you're having this problem. Have you tried having a login-request socket, doing a hand-shake there, then sending clients to their own socket?

Alternatively, you can handle this at the application layer by handling all incoming data on one thread, in which you figure out the source of the individual packet, then task to the thread that's dealing with that client.
 
Share this answer
 
Comments
srikantpanda 22-Dec-11 6:05am    
HI Albert,

No, they are not in the same socket. Infact with accpet each client gets different sockets and so on receive.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900