Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C Windows Server socket
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 21-Dec-11 3:51am
Edited 21-Dec-11 3:54am
v2
Comments
Chuck O'Toole at 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 at 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");
}
}
}
}
}
}
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

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).
  Permalink  
Comments
Albert Holguin at 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 at 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 at 23-Dec-11 6:04am
   
Chuck did the real work here, so we should be thanking him... ;) ....thanks chuck, :)
srikantpanda at 23-Dec-11 6:35am
   
yeah how i can forget Chuk..he is just awesome....:):)
 
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

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.
  Permalink  
Comments
srikantpanda at 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)

  Print Answers RSS
0 Maciej Los 205
1 Richard MacCutchan 185
2 DamithSL 170
3 Tomas Takac 146
4 OriginalGriff 132
0 OriginalGriff 5,130
1 DamithSL 4,237
2 Maciej Los 3,700
3 Kornfeld Eliyahu Peter 3,470
4 Sergey Alexandrovich Kryukov 2,846


Advertise | Privacy | Mobile
Web01 | 2.8.141216.1 | Last Updated 22 Dec 2011
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100