Hi,
I am writing a UDP based multi-threaded server in C on linux platform. I am facing this perticular problem. I launch a new thread when when first packet from client is received on the server port. Now I want that, all subseqent send/recv between that client and server should happen in the new thread i just created. But in my case every new packet received from the same client causes server to spawn the new thread. How can I get it work the way I want it to work?
Following is the code where I spawn new thread.
Code:
while (1)
{
signal(SIGINT,exit_cleanup);
if (shareddb->threadcount >= MAX_XCLIENTS)
{
printf("Maximum limit reached for client requests. Can not accept anymore requests.\n");
} else {
ServerSock[shareddb->threadcount]=getXSocket(&shareddb->serversockid[shareddb->threadcount]);
//printf("Socket: %d\n",shareddb->serversockid[shareddb->threadcount]);
if (ServerSock[shareddb->threadcount] == NULL)
{
exit(1);
}
if (setsockopt(shareddb->serversockid[shareddb->threadcount],SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1)
{
perror("setsockopt");
}
if ((bind(shareddb->serversockid[shareddb->threadcount],(XSocket *)ServerSock[shareddb->threadcount],sizeof(XSocket))) == -1 )
{
perror("Server Socket Bind Error:");
}
XServerSockid=shareddb->serversockid[shareddb->threadcount];
if ((numbytes=recvfrom(XServerSockid,(XPacket *)&xpacket,sizeof(XPacket),0,(XSocket *)&RemoteSock, &sin_size)) == -1) {
perror("recvfrom");
exit(1);
}
//signal(SIGINT,exit_cleanup);
printf("UDP Connection received from XClient Source IP %s Port:%d Socket: %d \n",inet_ntoa(RemoteSock.sin_addr),ntohs(RemoteSock.sin_port),shareddb->serversockid[shareddb->threadcount]);
memcpy(&threadsdata.xpacket,&xpacket,sizeof(XPacket));
memcpy(&threadsdata.xsocket,&RemoteSock,sizeof(XSocket_in));
threadsdata.ServerSockid=shareddb->serversockid[shareddb->threadcount];
threadsdata.first=1;
rc=pthread_create(&shareddb->clientthreadid[shareddb->threadcount],&attr,HandleXConns,(void *)&threadsdata);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
} else {
memset(debugstr,'\0',sizeof(debugstr));
sprintf(debugstr,"XServer: Thread started id: %d \n",(int)shareddb->clientthreadid[shareddb->threadcount]);
dbgtrace(__FUNCTION__,debugstr);
shareddb->threadcount++;
}
}
}
When I run it I see following output. (Marked the line showing problem area )
./xserver
main : Shared memory for shared information database is created: id = 173473825
main : Shared memory pointer acquired: address = 0x0805cddc
UDP Connection received from XClient Source IP 10.6.250.55 Port:32811 Socket: 3
decodeXpacket : Version: 0x0001 Opcode: 0x0002 Message length: 1
decodeXpacket : Received XDMCP "Query" Packet.
decodeXpacket : Decoding XDMCP "Query" Packet.
decodeXpacket : Authenetication name length: 0
decodeXpacket : Authorization Data: 0
sendXpacket : Sending XDMCP "Willing" Packet.
sendXpacket : version: 0x0001 opcode: 0x0005 Message length: 31 Authname: 0x00
sendXpacket : XDMCP "Willing" Packet sent.
main : XServer: Thread started id: 8194 <<<<< Thread 1
UDP Connection received from XClient Source IP 10.6.250.55 Port:32811 Socket: 6 <<<< This should be received in Thread 1
main : XServer: Thread started id: 16387 <<<< Thread 2 (not required)
Unknown Packet. Can not proceed. <<<Errors as the this is continuation packet for Thread 1.
sendXpacket : Sending XDMCP "Decline" Packet.
sendXpacket : version: 0x0001 opcode: 0x0009 Message length: 6144 Authname: 0x00
sendXpacket : XDMCP "Decline" Packet sent.
Here is the snippet of the code in thread handler function HandleXConns()
Code:
void * HandleXConns(void *arg)
{
struct thread_data *threadsdata;
XPacket xpacket;
XSocket_in xsocket,RemoteSock;
XMode querytype;
int addr_len,packetlen;
boolean sendresult,receiveresult;
int bytes_received;
static int first=1;
threadsdata=(struct thread_data *)arg;
memcpy(&xpacket,&(threadsdata->xpacket),sizeof(XPacket));
memcpy(&xsocket,&(threadsdata->xsocket),sizeof(XSocket_in));
if (threadsdata->first && (htons(xpacket.opcode) == QUERY))
{
decodeXpacket(&xpacket);
threadsdata->first=0;
} else if (threadsdata->first && (htons(xpacket.opcode) == INDIRECTQUERY))
{
decodeXpacket(&xpacket);
threadsdata->first=0;
} else {
printf("Unknown Packet. Can not proceed.\n");
declinestatus = 2;
sendXpacket(DECLINE,threadsdata->ServerSockid,xsocket);
declinestatus = 0;
pthread_exit(NULL);
}
querytype=WILLING;
if ((sendresult=sendXpacket(querytype,threadsdata->ServerSockid,xsocket)) == FALSE)
{
memset(debugstr,'\0',sizeof(debugstr));
sprintf(debugstr,"XDMCP session failed. Could not send the \"%s\"packet.\n",decodeIPCMessage(querytype));
dbgtrace(__FUNCTION__,debugstr);
undbgtrace(__FUNCTION__,debugstr);
//terminateall(__FUNCTION__);
pthread_exit(NULL);
} else {
printf("\n");
memset(xpacket.data,'\0',sizeof(xpacket.data));
packetlen=(genlength + sizeof(xpacket.data));
addr_len=sizeof(XSocket);
bytes_received=recvfrom(threadsdata->ServerSockid, (XPacket *)&xpacket, packetlen, 0,(XSocket *)&RemoteSock, &addr_len);
memset(debugstr,'\0',sizeof(debugstr));
sprintf(debugstr,"Total Bytes received : %d\n",bytes_received);
dbgtrace(__FUNCTION__,debugstr);
....contd..
Is there anything obvious that I am missing here.?
Thanks,