Solved

Reg:Multi thread Server for chat  application

Posted on 2007-11-18
23
245 Views
Last Modified: 2010-04-01
Hii ,
    I am trying to create a simple multithreaded chat application. I am facing problems while creating a multiple threads and executing them ,multiple clients are able to connect to the serever but only the latest connected is able to exchange data as the remaining are almost dead.
following is my code :


#include <winsock2.h>

#include <iostream>

using namespace std;
 

struct CLIENT_INFO

{

    SOCKET hClientSocket ;

    struct sockaddr_in clientAddr ;

} ;
 

char szServerIPAddr[ ] = "0.0.0.0" ;     // Put here the IP address of the server

int nServerPort = 1035 ;                    // The server port that will be used by

                                            // clients to talk with the server
 

bool InitWinSock2_0( ) ;

int ClientThread( LPVOID lpData ) ;
 

int main( )

{

    if ( ! InitWinSock2_0( ) )

    {

        cout << "Unable to Initialize Windows Socket environment" << WSAGetLastError( ) << endl ;

        return -1 ;

    }
 

    SOCKET hServerSocket ;
 

    hServerSocket = socket(

        AF_INET,        // The address family. AF_INET specifies TCP/IP

        SOCK_STREAM,    // Protocol type. SOCK_STREM specified TCP

        0               // Protoco Name. Should be 0 for AF_INET address family

        ) ;

    if ( hServerSocket == INVALID_SOCKET )

    {

        cout << "Unable to create Server socket" << endl ;

        // Cleanup the environment initialized by WSAStartup()

        WSACleanup( ) ;

        return -1 ;

    }

	cout<<"socket: ready"<<"\n";
 
 

    // Create the structure describing various Server parameters

    struct sockaddr_in serverAddr ;
 

    serverAddr . sin_family = AF_INET ;     // The address family. MUST be AF_INET

    serverAddr . sin_addr . s_addr = inet_addr( szServerIPAddr ) ;

    serverAddr . sin_port = htons( nServerPort ) ;
 

    // Bind the Server socket to the address & port

    if ( bind( hServerSocket, ( struct sockaddr * ) &serverAddr, sizeof( serverAddr ) ) == SOCKET_ERROR )

    {

        cout << "Unable to bind to " << szServerIPAddr << " port " << nServerPort << endl ;

        // Free the socket and cleanup the environment initialized by WSAStartup()

        closesocket( hServerSocket ) ;

        WSACleanup( ) ;

        return -1 ;

    }
 

   cout<<"socket: binded"<<"\n";

    // Put the Server socket in listen state so that it can wait for client connections

    if ( listen( hServerSocket, SOMAXCONN ) == SOCKET_ERROR )

    {

        cout << "Unable to put server in listen state" << endl ;

        // Free the socket and cleanup the environment initialized by WSAStartup()

        closesocket( hServerSocket ) ;

        WSACleanup( ) ;

        return -1 ;

    }
 

	cout<<"socket: listening"<<"\n";

    // Start the infinite loop

    while ( true )

    {

        // As the socket is in listen mode there is a connection request pending.

        // Calling accept( ) will succeed and return the socket for the request.

        SOCKET hClientSocket ;

        struct sockaddr_in clientAddr ;

        int nSize = sizeof( clientAddr ) ;
 

        hClientSocket = accept( hServerSocket, ( struct sockaddr *) &clientAddr, &nSize ) ;

        if ( hClientSocket == INVALID_SOCKET )

        {

            cout << "accept( ) failed" << endl ;

        }

        else

        {

			cout<<"socket: accepted"<<"\n";

            HANDLE hClientThread ;

            struct CLIENT_INFO clientInfo ;

            DWORD dwThreadId ;
 

            clientInfo . clientAddr = clientAddr ;

            clientInfo . hClientSocket = hClientSocket ;
 

            cout << "Client connected from " << inet_ntoa( clientAddr . sin_addr ) << endl ;
 

            // Start the client thread

            hClientThread = CreateThread( NULL, 0,

                ( LPTHREAD_START_ROUTINE ) ClientThread,

                ( LPVOID ) &clientInfo, 0, &dwThreadId ) ;

			

            if ( hClientThread == NULL )

            {

                cout << "Unable to create client thread" << endl ;

            }

            else

            {

                CloseHandle( hClientThread ) ;

            }

        }

    }
 

    closesocket( hServerSocket ) ;

    WSACleanup( ) ;

    return 0 ;

}
 

bool InitWinSock2_0( )

{

    WSADATA wsaData ;

    WORD wVersion = MAKEWORD( 2, 0 ) ;
 

    if ( ! WSAStartup( wVersion, &wsaData ) )

        return true ;
 

    return false ;

}
 

int ClientThread( LPVOID lpData )

{

    CLIENT_INFO *pClientInfo = ( CLIENT_INFO * ) lpData ;

    char szBuffer[ 1024 ] ;

    int nLength ;
 

    while ( 1 )

    {

        nLength = recv( pClientInfo -> hClientSocket, szBuffer, sizeof( szBuffer ), 0 ) ;

		cout<<nLength<<"\n";

		

        if ( nLength > 0 )

        {

            szBuffer[ nLength ] = '\0' ;

            cout << "Received " << szBuffer << " from " << inet_ntoa( pClientInfo -> clientAddr . sin_addr ) << endl ;
 

            // Convert the string to upper case and send it back, if its not QUIT

           // strupr( szBuffer ) ;

            if ( strcmp( szBuffer, "QUIT" ) == 0 )

            {

                closesocket( pClientInfo -> hClientSocket ) ;

                return 0 ;

            }

            // send( ) may not be able to send the complete data in one go.

            // So try sending the data in multiple requests

            int nCntSend = 0 ;

             

            char *pBuffer = szBuffer ;
 

            while ( ( nCntSend = send( pClientInfo -> hClientSocket, pBuffer, nLength, 0 ) != nLength ) )

            {

                if ( nCntSend == -1 )

                {

                    cout << "Error sending the data to " << inet_ntoa( pClientInfo -> clientAddr . sin_addr ) << endl ;

                    break ;

                }

                if ( nCntSend == nLength )

                    break ;
 

                pBuffer += nCntSend ;

                nLength -= nCntSend ;

            }

        }

        else

        {

            cout << "Error reading the data from " << inet_ntoa( pClientInfo -> clientAddr . sin_addr ) << endl ;

			break;
 

        }

    }
 
 
 

    return 0 ;

}

Open in new window

0
Comment
Question by:njoy143
  • 9
  • 8
  • 3
  • +2
23 Comments
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 20310360
you need to have clear this:
multiple threads can send packets to the same socket port.
Just one thread can listen a socket port.
So, in a multithreaded environment, you need a single port listener than forwards the message to the other threads or choose a unique destination thread.
0
 

Author Comment

by:njoy143
ID: 20310437
Jaime,Thanks for the suggestion,I am listening at a single port, but i think i am missing some thing while creating multiple threads. iIam succesfull in connecting multiple clients to the server, but while exchanging messages only the latest connected client is able to exchange with  the server.
Please, any suggestings in modifying the code.
0
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 20310499
You cannot use recv in each thread, you have to do it in the main thread or a listener thread, and forward to the other threads,
0
 

Author Comment

by:njoy143
ID: 20310612
Jaime, thanks but i still cannot get your point.
0
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 20310791
hmm, appears to be the listen() should be inside the while loop, so once you listen and accept the first connection, you will listen again.
If you application is printing some error message, please post.
0
 
LVL 11

Expert Comment

by:DeepuAbrahamK
ID: 20312460
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20312882
>>>> You cannot use recv in each thread, you have to do
>>>> it in the main thread or a listener thread, and forward
>>>> to the other threads,

That is not true. But each of the recv is blocking. So, the 'chat' stops (means the thread was waiting for input) if  the external client program was not sending anymore. How did you connect? Have you multiple client programs, one for each thread?.


>>>> nCntSend = send( pClientInfo -> hClientSocket, pBuffer, nLength, 0 )
Why do you send the same message back?


>>>> struct CLIENT_INFO clientInfo ;
That is the main problem. The clientInfo was a local variable which was destroyed after each iteration. That's why the older threads cannot work properly cause their clientInfo was invalid. You have to create the threadinfo by

   struct CLIENT_INFO* pclientInfo = new CLIENT_INFO ;

and then pass pclientInfo to the threads. You also could/should store all these pointers in an array in the main so taht you can disconnect at end of program.


  struct CLIENT_INFO* clientInfoArr[MAX_THREADS];

  int nclients = 0;
  while (true)
  {
           ...
           clientInfoArr[nclients] = new CLIENT_INFO ;
           clientInfoArr[nclients]->hClientSocket =  hClientSocket;
           ...
           nclients++;
 
  }

Regards, Alex
0
 

Author Comment

by:njoy143
ID: 20317132
Alex,
        Thanks for the suggestions, I am still having problem with the code.Now a new problem came in to picture ,initially i was able to assign 0.0.0.0 for my server and was able to bind succesfully, but now i am  not able to bind unless i change it to 127.0.0.1.
comming to the threads issue. can you please explain it in more detail, i have implemented your suggestions ,
included an array in the main.
i think the below code should give a better idea.
now when i run the modified program i am  am getting printed""Error reading the data from " i.e from the client thread so now the server is not able to recieve the data. the value of nLength is -1.Your valuble suggestions should help me complete my work.


#include <winsock2.h>

#include <iostream>

using namespace std;
 

struct CLIENT_INFO

{

    SOCKET hClientSocket ;

    struct sockaddr_in clientAddr ;

} ;
 

char szServerIPAddr[ ] = "127.0.0.1" ;     // Put here the IP address of the server

int nServerPort = 1035 ;                    // The server port that will be used by

                                            // clients to talk with the server
 

bool InitWinSock2_0( ) ;

int ClientThread( LPVOID lpData ) ;
 

int main( )

{
 
 

    if ( ! InitWinSock2_0( ) )

    {

        cout << "Unable to Initialize Windows Socket environment" << WSAGetLastError( ) << endl ;

        return -1 ;

    }

	 struct CLIENT_INFO* clientInfoArr[100];
 

   int nclients = 0;
 
 

    SOCKET hServerSocket ;
 

    hServerSocket = socket(

        AF_INET,        // The address family. AF_INET specifies TCP/IP

        SOCK_STREAM,    // Protocol type. SOCK_STREM specified TCP

        0               // Protoco Name. Should be 0 for AF_INET address family

        ) ;

    if ( hServerSocket == INVALID_SOCKET )

    {

        cout << "Unable to create Server socket" << endl ;

        // Cleanup the environment initialized by WSAStartup()

        WSACleanup( ) ;

        return -1 ;

    }

	cout<<"socket: ready"<<"\n";
 
 

    // Create the structure describing various Server parameters

    struct sockaddr_in serverAddr ;
 

    serverAddr . sin_family = AF_INET ;     // The address family. MUST be AF_INET

    serverAddr . sin_addr . s_addr = inet_addr( szServerIPAddr ) ;

    serverAddr . sin_port = htons( nServerPort ) ;
 

    // Bind the Server socket to the address & port

    if ( bind( hServerSocket, ( struct sockaddr * ) &serverAddr, sizeof( serverAddr ) ) == SOCKET_ERROR )

    {

        cout << "Unable to bind to " << szServerIPAddr << " port " << nServerPort << endl ;

        // Free the socket and cleanup the environment initialized by WSAStartup()

        closesocket( hServerSocket ) ;

        WSACleanup( ) ;

        return -1 ;

    }
 

   cout<<"socket: binded"<<"\n";

    // Put the Server socket in listen state so that it can wait for client connections

    if ( listen( hServerSocket, SOMAXCONN ) == SOCKET_ERROR )

    {

        cout << "Unable to put server in listen state" << endl ;

        // Free the socket and cleanup the environment initialized by WSAStartup()

        closesocket( hServerSocket ) ;

        WSACleanup( ) ;

        return -1 ;

    }
 

	cout<<"socket: listening"<<"\n";

    // Start the infinite loop

    while ( true )

    {

        // As the socket is in listen mode there is a connection request pending.

        // Calling accept( ) will succeed and return the socket for the request.

        SOCKET hClientSocket ;

        struct sockaddr_in clientAddr ;

        int nSize = sizeof( clientAddr ) ;
 

        hClientSocket = accept( hServerSocket, ( struct sockaddr *) &clientAddr, &nSize ) ;

        if ( hClientSocket == INVALID_SOCKET )

        {

            cout << "accept( ) failed" << endl ;

        }

        else

        {

			cout<<"socket: accepted"<<"\n";

            HANDLE hClientThread ;

            

            DWORD dwThreadId ;

		   clientInfoArr[nclients] = new CLIENT_INFO ;

           clientInfoArr[nclients]->hClientSocket =  hClientSocket;

		   clientInfoArr[nclients]->clientAddr = clientAddr ;

		   struct CLIENT_INFO* clientInfo =new CLIENT_INFO;

		   clientInfo->clientAddr=clientInfoArr[nclients]->clientAddr;

		   clientInfo->hClientSocket= clientInfoArr[nclients]->hClientSocket;

           cout << "Client connected from " << inet_ntoa( clientAddr . sin_addr ) << endl ;

		   cout<<nclients<<"\n";
 

            // Start the client thread

		  // for(int i=0;i<nclients;i++)

		   //{

            hClientThread = CreateThread( NULL, 0,

                ( LPTHREAD_START_ROUTINE ) ClientThread,

                ( LPVOID ) &clientInfo, 0, &dwThreadId ) ;

			

            if ( hClientThread == NULL )

            {

                cout << "Unable to create client thread" << endl ;

            }

            else

            {

                CloseHandle( hClientThread ) ;

            }

		  // }
 

			nclients++;

        }

    }
 

    closesocket( hServerSocket ) ;

    WSACleanup( ) ;

    return 0 ;

}
 

bool InitWinSock2_0( )

{

    WSADATA wsaData ;

    WORD wVersion = MAKEWORD( 2, 0 ) ;
 

    if ( ! WSAStartup( wVersion, &wsaData ) )

        return true ;
 

    return false ;

}
 

int ClientThread(LPVOID lpData)

{

	

	//struct CLIENT_INFO* pclientInfo;

	 struct CLIENT_INFO* pclientInfo = new CLIENT_INFO ;
 

    CLIENT_INFO *pClientInfo = ( CLIENT_INFO * ) lpData ;

	

 // pClientInfo->

     char szBuffer[ 1024 ] ;

     int nLength ;
 

    while ( 1 )

    {

        nLength = recv( pClientInfo -> hClientSocket, szBuffer, sizeof( szBuffer ), 0 ) ;

		cout<<nLength<<"\n";

		

        if ( nLength > 0 )

        {

            szBuffer[ nLength ] = '\0' ;

            cout << "Received " << szBuffer << " from " << inet_ntoa( pClientInfo -> clientAddr . sin_addr ) << endl ;
 

            // Convert the string to upper case and send it back, if its not QUIT

           // strupr( szBuffer ) ;

            if ( strcmp( szBuffer, "QUIT" ) == 0 )

            {

                closesocket( pClientInfo -> hClientSocket ) ;

                return 0 ;

            }

            // send( ) may not be able to send the complete data in one go.

            // So try sending the data in multiple requests

            int nCntSend = 0 ;

             

            char *pBuffer = szBuffer ;
 

            while ( ( nCntSend = send( pClientInfo -> hClientSocket, pBuffer, nLength, 0 ) != nLength ) )

            {

                if ( nCntSend == -1 )

                {

                    cout << "Error sending the data to " << inet_ntoa( pClientInfo -> clientAddr . sin_addr ) << endl ;

                    break ;

                }

                if ( nCntSend == nLength )

                    break ;
 

                pBuffer += nCntSend ;

                nLength -= nCntSend ;

            }

        }

        else

        {

            cout << "Error reading the data from " << inet_ntoa( pClientInfo ->clientAddr . sin_addr ) << endl ;

			break;
 

        }

    }
 
 
 

    return 0 ;

}

Open in new window

0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20318043
>>>>> char szServerIPAddr[ ] = "127.0.0.1" ;

You have to get it to work with the address you got when making 'ping' at the command line (DOS Box).

>>>> int nServerPort = 1035 ;
Actually it is an unsigned short and you should use a higher number:

   unsigned short nServerPort = 45123;

... to be continued ...

Regards, Alex
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20318116
>>>>               clientInfoArr[nclients] = new CLIENT_INFO ;

You need to define the array above the endless loop:

   const int MAX_CLIENTS = 100;  // choose an appropriate number
   CLIENT_INFO*  clientInfoArr[MAX_CLIENTS] = NULL;
   int nclients = 0;

>>>> struct CLIENT_INFO* clientInfo =new CLIENT_INFO;
>>>>   clientInfo->clientAddr=clientInfoArr[nclients]->clientAddr;
>>>>    clientInfo->hClientSocket= clientInfoArr[nclients]->hClientSocket;
That is obsolete now.

>>>>               cout<<nclients<<"\n";
Maybe better:
     cout << nclients+1 << endl;


>>>> hClientThread = CreateThread( NULL, 0,
>>>>                ( LPTHREAD_START_ROUTINE ) ClientThread,
>>>>                ( LPVOID ) &clientInfo, 0, &dwThreadId ) ;

            hClientThread = CreateThread( NULL, 0,
                ( LPTHREAD_START_ROUTINE ) ClientThread,
                ( LPVOID ) clientInfoArr[nclients], 0, &dwThreadId ) ;  

>>> struct CLIENT_INFO* pclientInfo = new CLIENT_INFO ;

omit
0
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 500 total points
ID: 20318267
>>>> hClientSocket = accept( hServerSocket, ( struct sockaddr *) &clientAddr, &nSize ) ;
That blocks the main loop, so that you have no chance to quit from server

There are two ways out:

1. Use select with timeout *before* accept to find out whether there is any client to connect. In case of timeout you can do other actions, e. g. check for termination.

 // Start the infinite loop
 while ( true )
 {
    // fd_set manages an array of sockets
    fd_set          readSockets;
    struct timeval  tval;

    // set host sockat as first and only element
    FD_ZERO(&readSockets);
    FD_SET(hServerSocket, &readSockets);

    // init timeout
    tval.tv_sec  = 0;
    tval.tv_usec = 100000; // 100 milliseconds

    int result = select(hServerSocket + 1, &readSockets, NULL, NULL, &tval);

    if (result == 0)
    {
           // timeout: we now can check whether the user wants to stop
           ...
           // if not let's try again
           continue;    
    }    
   
     // As the socket is in listen mode there is a connection request pending.
     // Calling accept( ) will succeed and return the socket for the request.
     SOCKET hClientSocket ;
     ...


2. Set the socket to non-blocking what means that 'accept' would return immediately with error -1 and GetLastError() == WSAE_WOULDBLOCK in almost all cases. Then 'sleep' a little while before you try next accept.

  DWORD on = 1;
  ioctlsocket(hServerSocket, FIONBIO, &on);  // now non-blocking
 // Start the infinite loop
 while ( true )
 {
       ...
        hClientSocket = accept( hServerSocket, ( struct sockaddr *) &clientAddr, &nSize ) ;
        if ( hClientSocket == INVALID_SOCKET )
        {
               if (GetLastError() == WSAE_WOULDBLOCK)
               {
                      // check for termination
                      ...
                      Sleep(100);   // sleep a little while
                      continue;  // try again
               }

If timeout expired you could check whether there was an attempt to quit from program, e. g. by calling cin.peek(). You also could connect with a client and send "quit server" message. The client thread which receives such a message could set a global bool flag, e. g. 'stopChat' to true. In case of timeout you could check in main whether the stopChat was true and terminate all threads if so.

Terminating the threads should be made 'smoothfully'. In the clientInfoArr you have all clientInfo pointers sent to the threads. You can disconnect the client sockets what would cause them to return from recv with SOCKET_ERROR. Then, they should terminate by 'return' from thread function. The main thread should sleep a few seconds after disconnecting all client sockets and should then break the infinite loop.

Regards, Alex
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 

Author Comment

by:njoy143
ID: 20318272
Alex,
       Thanks for your help on solving the problem, i tried to implement the host Ip address(mine is 192.168.1.100),its working fine,comming to the thread problem,i have followed the steps you have mentioned, but still i am getting the out put where in the server is not able to recieve the data, probably there is some error in the   function clientthread.
Am i on the right path i.e. Is my approach correct.
I am adding the modified code.
Thanks for spending your valuble time..
I hope we should come with a Perfect solution soon...




#include <winsock2.h>

#include <iostream>

using namespace std;
 

struct CLIENT_INFO

{

    SOCKET hClientSocket ;

    struct sockaddr_in clientAddr ;

} ;
 

char szServerIPAddr[ ] = "192.168.1.100" ;     // Put here the IP address of the server

unsigned short nServerPort = 45123;

                // The server port that will be used by

                                            // clients to talk with the server
 

bool InitWinSock2_0( ) ;

int ClientThread( LPVOID lpData ) ;
 

int main( )

{
 
 

    if ( ! InitWinSock2_0( ) )

    {

        cout << "Unable to Initialize Windows Socket environment" << WSAGetLastError( ) << endl ;

        return -1 ;

    }

	 
 

   const int MAX_CLIENTS = 100;  // choose an appropriate number

   CLIENT_INFO * clientInfoArr[MAX_CLIENTS];

   int nclients = 0;
 
 
 

    SOCKET hServerSocket ;
 

    hServerSocket = socket(

        AF_INET,        // The address family. AF_INET specifies TCP/IP

        SOCK_STREAM,    // Protocol type. SOCK_STREM specified TCP

        0               // Protoco Name. Should be 0 for AF_INET address family

        ) ;

    if ( hServerSocket == INVALID_SOCKET )

    {

        cout << "Unable to create Server socket" << endl ;

        // Cleanup the environment initialized by WSAStartup()

        WSACleanup( ) ;

        return -1 ;

    }

	cout<<"socket: ready"<<"\n";
 
 

    // Create the structure describing various Server parameters

    struct sockaddr_in serverAddr ;
 

    serverAddr . sin_family = AF_INET ;     // The address family. MUST be AF_INET

    serverAddr . sin_addr . s_addr = inet_addr( szServerIPAddr ) ;

    serverAddr . sin_port = htons( nServerPort ) ;
 

    // Bind the Server socket to the address & port

    if ( bind( hServerSocket, ( struct sockaddr * ) &serverAddr, sizeof( serverAddr ) ) == SOCKET_ERROR )

    {

        cout << "Unable to bind to " << szServerIPAddr << " port " << nServerPort << endl ;

        // Free the socket and cleanup the environment initialized by WSAStartup()

        closesocket( hServerSocket ) ;

        WSACleanup( ) ;

        return -1 ;

    }
 

   cout<<"socket: binded"<<"\n";

    // Put the Server socket in listen state so that it can wait for client connections

    if ( listen( hServerSocket, SOMAXCONN ) == SOCKET_ERROR )

    {

        cout << "Unable to put server in listen state" << endl ;

        // Free the socket and cleanup the environment initialized by WSAStartup()

        closesocket( hServerSocket ) ;

        WSACleanup( ) ;

        return -1 ;

    }
 

	cout<<"socket: listening"<<"\n";
 

    // Start the infinite loop

	clientInfoArr[nclients] = new CLIENT_INFO ;

    while ( true )

    {

        // As the socket is in listen mode there is a connection request pending.

        // Calling accept( ) will succeed and return the socket for the request.

        SOCKET hClientSocket ;

        struct sockaddr_in clientAddr ;

        int nSize = sizeof( clientAddr ) ;
 

        hClientSocket = accept( hServerSocket, ( struct sockaddr *) &clientAddr, &nSize ) ;

		//cout<<inet_ntoa(clientAddr.sin_addr)<<"\n";

        if ( hClientSocket == INVALID_SOCKET )

        {

            cout << "accept( ) failed" << endl ;

        }

        else

        {

			cout<<"socket: accepted"<<"\n";

            HANDLE hClientThread ;

            

            DWORD dwThreadId ;

		   

           clientInfoArr[nclients]->hClientSocket =  hClientSocket;

		   clientInfoArr[nclients]->clientAddr = clientAddr ;

		   

           cout << "Client connected from " << inet_ntoa( clientAddr . sin_addr ) << endl ;

		   cout<<nclients+1<<"\n";
 

            // Start the client thread

		    

            hClientThread = CreateThread( NULL, 0,

                ( LPTHREAD_START_ROUTINE ) ClientThread,

                ( LPVOID ) &clientInfoArr[nclients], 0, &dwThreadId ) ;

			  cout<<dwThreadId<<"\n";

			

            if ( hClientThread == NULL )

            {

                cout << "Unable to create client thread" << endl ;

            }

            

			else

			{

               CloseHandle( hClientThread ) ;

			}

		   
 

			nclients++;

        }

    }
 

    closesocket( hServerSocket ) ;

    WSACleanup( ) ;

    return 0 ;

}
 

bool InitWinSock2_0( )

{

    WSADATA wsaData ;

    WORD wVersion = MAKEWORD( 2, 0 ) ;
 

    if ( ! WSAStartup( wVersion, &wsaData ) )

        return true ;
 

    return false ;

}
 

int ClientThread(LPVOID lpData)

{

	

	struct CLIENT_INFO* pclientInfo;

	 

    CLIENT_INFO *pClientInfo = ( CLIENT_INFO * ) lpData ;

	

     char szBuffer[ 1024 ] ;

     int nLength ;
 

    while ( 1 )

    {

        nLength = recv( pClientInfo -> hClientSocket, szBuffer, sizeof( szBuffer ), 0 ) ;

		cout<<nLength<<"\n";

		

        if ( nLength > 0 )

        {

            szBuffer[ nLength ] = '\0' ;

            cout << "Received " << szBuffer << " from " << inet_ntoa( pClientInfo -> clientAddr . sin_addr ) << endl ;
 

            // Convert the string to upper case and send it back, if its not QUIT

           // strupr( szBuffer ) ;

            if ( strcmp( szBuffer, "QUIT" ) == 0 )

            {

                closesocket( pClientInfo -> hClientSocket ) ;

                return 0 ;

            }

            // send( ) may not be able to send the complete data in one go.

            // So try sending the data in multiple requests

            int nCntSend = 0 ;

             

            char *pBuffer = szBuffer ;
 

			
 
 

            while ( ( nCntSend = send( pClientInfo -> hClientSocket, pBuffer, nLength, 0 ) != nLength ) )

            {

                if ( nCntSend == -1 )

                {

                    cout << "Error sending the data to " << inet_ntoa( pClientInfo -> clientAddr . sin_addr ) << endl ;

                    break ;

                }

                if ( nCntSend == nLength )

                    break ;
 

                pBuffer += nCntSend ;

                nLength -= nCntSend ;

            }

        }

        else

        {

            cout << "Error reading the data from " << inet_ntoa( pClientInfo ->clientAddr . sin_addr ) << endl ;

			break;
 

        }

    }
 
 
 

    return 0 ;

}

Open in new window

0
 

Author Comment

by:njoy143
ID: 20318288
Alex,
       I am sorry i just saw your latest comment, please ignore my previous one, i shall  follow your recomendations in the latest comment and let you know the update.
thanks
njoy143
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20318303
>>>> &clientInfoArr[nclients]

remove the '&'.  The clientInfoArr already is an array of pointers. So, if you use '&' you pass the address of a pointer but you should pass the pointer itself and not its address.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20318306
>>>> unsigned short nServerPort = 45123;
That is an arbitrary number. The only thing you have to consider is to choose a number between 2001 and 65535 (max unsigned short) *and* the number should be not be used by any other server/service by accident. You would get an error when binding the socket in that case.
0
 

Author Comment

by:njoy143
ID: 20318349
Alex,
        Before i start to go through  the 2 ways that you have mentioned ,i have encountered that when i open multiple clients(more than 1) the server.exe is getting closed saying that an error has occured,when noticed on the window it is written that: Unhandled Exception:System.NullReferenceEception:"Object reference not set to an onstance of the object.
its pointing towards line 107 in the program" i.e at
 clientInfoArr[nclients]->hClientSocket = hClientSocket;
Thanks once again for your valuble suggestions.
njoy143
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20318357
Did you change to

hClientThread = CreateThread( NULL, 0,
                ( LPTHREAD_START_ROUTINE ) ClientThread,
                ( LPVOID ) clientInfoArr[nclients], 0, &dwThreadId ) ;
0
 

Author Comment

by:njoy143
ID: 20318365
yes,
hClientThread = CreateThread( NULL, 0,
                ( LPTHREAD_START_ROUTINE ) ClientThread,
                ( LPVOID ) clientInfoArr[nclients], 0, &dwThreadId ) ;
0
 

Author Comment

by:njoy143
ID: 20318370
Here is the  code


#include <winsock2.h>

#include <iostream>

using namespace std;
 

struct CLIENT_INFO

{

    SOCKET hClientSocket ;

    struct sockaddr_in clientAddr ;

} ;
 

char szServerIPAddr[ ] = "192.168.1.100" ;     // Put here the IP address of the server

unsigned short nServerPort = 5026;

                // The server port that will be used by

                                            // clients to talk with the server
 

bool InitWinSock2_0( ) ;

int ClientThread( LPVOID lpData ) ;
 

int main( )

{
 
 

    if ( ! InitWinSock2_0( ) )

    {

        cout << "Unable to Initialize Windows Socket environment" << WSAGetLastError( ) << endl ;

        return -1 ;

    }

	 
 

   const int MAX_CLIENTS = 100;  // choose an appropriate number

   CLIENT_INFO * clientInfoArr[MAX_CLIENTS];

   int nclients = 0;
 
 
 

    SOCKET hServerSocket ;
 

    hServerSocket = socket(

        AF_INET,        // The address family. AF_INET specifies TCP/IP

        SOCK_STREAM,    // Protocol type. SOCK_STREM specified TCP

        0               // Protoco Name. Should be 0 for AF_INET address family

        ) ;

    if ( hServerSocket == INVALID_SOCKET )

    {

        cout << "Unable to create Server socket" << endl ;

        // Cleanup the environment initialized by WSAStartup()

        WSACleanup( ) ;

        return -1 ;

    }

	cout<<"socket: ready"<<"\n";
 
 

    // Create the structure describing various Server parameters

    struct sockaddr_in serverAddr ;
 

    serverAddr . sin_family = AF_INET ;     // The address family. MUST be AF_INET

    serverAddr . sin_addr . s_addr = inet_addr( szServerIPAddr ) ;

    serverAddr . sin_port = htons( nServerPort ) ;
 

    // Bind the Server socket to the address & port

    if ( bind( hServerSocket, ( struct sockaddr * ) &serverAddr, sizeof( serverAddr ) ) == SOCKET_ERROR )

    {

        cout << "Unable to bind to " << szServerIPAddr << " port " << nServerPort << endl ;

        // Free the socket and cleanup the environment initialized by WSAStartup()

        closesocket( hServerSocket ) ;

        WSACleanup( ) ;

        return -1 ;

    }
 

   cout<<"socket: binded"<<"\n";

    // Put the Server socket in listen state so that it can wait for client connections

    if ( listen( hServerSocket, SOMAXCONN ) == SOCKET_ERROR )

    {

        cout << "Unable to put server in listen state" << endl ;

        // Free the socket and cleanup the environment initialized by WSAStartup()

        closesocket( hServerSocket ) ;

        WSACleanup( ) ;

        return -1 ;

    }
 

	cout<<"socket: listening"<<"\n";
 

    // Start the infinite loop

	clientInfoArr[nclients] = new CLIENT_INFO ;

    while ( true )

    {

        // As the socket is in listen mode there is a connection request pending.

        // Calling accept( ) will succeed and return the socket for the request.

        SOCKET hClientSocket ;

        struct sockaddr_in clientAddr ;

        int nSize = sizeof( clientAddr ) ;
 

        hClientSocket = accept( hServerSocket, ( struct sockaddr *) &clientAddr, &nSize ) ;

		//cout<<inet_ntoa(clientAddr.sin_addr)<<"\n";

        if ( hClientSocket == INVALID_SOCKET )

        {

            cout << "accept( ) failed" << endl ;

        }

        else

        {

			cout<<"socket: accepted"<<"\n";

            HANDLE hClientThread ;

            

            DWORD dwThreadId ;

		   

           clientInfoArr[nclients]->hClientSocket = hClientSocket;

		   clientInfoArr[nclients]->clientAddr = clientAddr ;

		   

           cout << "Client connected from " << inet_ntoa( clientAddr . sin_addr ) << endl ;

		   cout<<nclients+1<<"\n";
 

            // Start the client thread

		    

            hClientThread = CreateThread( NULL, 0,

                ( LPTHREAD_START_ROUTINE ) ClientThread,

                ( LPVOID ) clientInfoArr[nclients], 0, &dwThreadId ) ;

			  cout<<dwThreadId<<"\n";

			

            if ( hClientThread == NULL )

            {

                cout << "Unable to create client thread" << endl ;

            }

            

			else

			{

               CloseHandle( hClientThread ) ;

			}

		   
 

			nclients++;

        }

    }
 

    closesocket( hServerSocket ) ;

    WSACleanup( ) ;

    return 0 ;

}
 

bool InitWinSock2_0( )

{

    WSADATA wsaData ;

    WORD wVersion = MAKEWORD( 2, 0 ) ;
 

    if ( ! WSAStartup( wVersion, &wsaData ) )

        return true ;
 

    return false ;

}
 

int ClientThread(LPVOID lpData)

{

	

	struct CLIENT_INFO* pclientInfo;

	 

    CLIENT_INFO *pClientInfo = ( CLIENT_INFO * ) lpData ;

	

     char szBuffer[ 1024 ] ;

     int nLength ;
 

    while ( 1 )

    {

        nLength = recv( pClientInfo -> hClientSocket, szBuffer, sizeof( szBuffer ), 0 ) ;

		cout<<nLength<<"\n";

		

        if ( nLength > 0 )

        {

            szBuffer[ nLength ] = '\0' ;

            cout << "Received " << szBuffer << " from " << inet_ntoa( pClientInfo -> clientAddr . sin_addr ) << endl ;
 

            // Convert the string to upper case and send it back, if its not QUIT

           // strupr( szBuffer ) ;

            if ( strcmp( szBuffer, "QUIT" ) == 0 )

            {

                closesocket( pClientInfo -> hClientSocket ) ;

                return 0 ;

            }

            // send( ) may not be able to send the complete data in one go.

            // So try sending the data in multiple requests

            int nCntSend = 0 ;

             

            char *pBuffer = szBuffer ;
 

			
 
 

            while ( ( nCntSend = send( pClientInfo -> hClientSocket, pBuffer, nLength, 0 ) != nLength ) )

            {

                if ( nCntSend == -1 )

                {

                    cout << "Error sending the data to " << inet_ntoa( pClientInfo -> clientAddr . sin_addr ) << endl ;

                    break ;

                }

                if ( nCntSend == nLength )

                    break ;
 

                pBuffer += nCntSend ;

                nLength -= nCntSend ;

            }

        }

        else

        {

            cout << "Error reading the data from " << inet_ntoa( pClientInfo ->clientAddr . sin_addr ) << endl ;

			break;
 

        }

    }
 
 
 

    return 0 ;

}

Open in new window

0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20318458
>>>>            clientInfoArr[nclients]->hClientSocket = hClientSocket;
Before that you need to create the pointer with 'new'

          clientInfoArr[nclients] = new CLIENT_INFO;

>>>>       struct CLIENT_INFO* pclientInfo;
You should remove that in ClientThread

>>>> Exception:System.NullReferenceEception
Looks like managed C++ ????

0
 
LVL 4

Expert Comment

by:yuy2002
ID: 20318746
See the code below, maybe can help u.
#include <winsock2.h>

#include <iostream>

using namespace std;

 

struct CLIENT_INFO

{

    SOCKET hClientSocket ;

    struct sockaddr_in clientAddr ;

} ;

 

char szServerIPAddr[ ] = "127.0.0.1" ;     // Put here the IP address of the server

int nServerPort = 1035 ;                    // The server port that will be used by

                                            // clients to talk with the server

 

bool InitWinSock2_0( ) ;

int ClientThread( LPVOID lpData ) ;

 

int main( )

{

 

 

    if ( ! InitWinSock2_0( ) )

    {

        cout << "Unable to Initialize Windows Socket environment" << WSAGetLastError( ) << endl ;

        return -1 ;

    }

	 struct CLIENT_INFO* clientInfoArr[100];

 

   int nclients = 0;

 

 

    SOCKET hServerSocket ;

  

    hServerSocket = socket(

        AF_INET,        // The address family. AF_INET specifies TCP/IP

        SOCK_STREAM,    // Protocol type. SOCK_STREM specified TCP

        0               // Protoco Name. Should be 0 for AF_INET address family

        ) ;

    if ( hServerSocket == INVALID_SOCKET )

    {

        cout << "Unable to create Server socket" << endl ;

        // Cleanup the environment initialized by WSAStartup()

        WSACleanup( ) ;

        return -1 ;

    }

	cout<<"socket: ready"<<"\n";
 

 

    // Create the structure describing various Server parameters

    struct sockaddr_in serverAddr ;

 

    serverAddr . sin_family = AF_INET ;     // The address family. MUST be AF_INET

    serverAddr . sin_addr . s_addr = inet_addr( szServerIPAddr ) ;

    serverAddr . sin_port = htons( nServerPort ) ;

 

    // Bind the Server socket to the address & port

    if ( bind( hServerSocket, ( struct sockaddr * ) &serverAddr, sizeof( serverAddr ) ) == SOCKET_ERROR )

    {

        cout << "Unable to bind to " << szServerIPAddr << " port " << nServerPort << endl ;

        // Free the socket and cleanup the environment initialized by WSAStartup()

        closesocket( hServerSocket ) ;

        WSACleanup( ) ;

        return -1 ;

    }

 

    cout<<"socket: binded"<<"\n";

    // Put the Server socket in listen state so that it can wait for client connections

    if ( listen( hServerSocket, SOMAXCONN ) == SOCKET_ERROR )

    {

        cout << "Unable to put server in listen state" << endl ;

        // Free the socket and cleanup the environment initialized by WSAStartup()

        closesocket( hServerSocket ) ;

        WSACleanup( ) ;

        return -1 ;

    }

 

	cout<<"socket: listening"<<"\n";

	struct CLIENT_INFO *clientInfo = new CLIENT_INFO;

	SOCKET hClientSocket ;

    struct sockaddr_in clientAddr ;

    // Start the infinite loop

    while ( true )

    {

        // As the socket is in listen mode there is a connection request pending.

        // Calling accept( ) will succeed and return the socket for the request.

        

        int nSize = sizeof( clientAddr ) ;

 

        hClientSocket = accept( hServerSocket, ( struct sockaddr *) &clientAddr, &nSize ) ;

        if ( hClientSocket == INVALID_SOCKET )

        {

            cout << "accept( ) failed" << endl ;

			return -1 ;

        }

        

			cout<<"socket: accepted"<<"\n";

			cout<<"hClientSocket = "<<hClientSocket<<"\n";

            HANDLE hClientThread ;

            

            DWORD dwThreadId ;

//		   clientInfoArr[nclients] = new CLIENT_INFO ;

//         clientInfoArr[nclients]->hClientSocket =  hClientSocket;

//		   clientInfoArr[nclients]->clientAddr = clientAddr ;

		   

//		   clientInfo->clientAddr=clientInfoArr[nclients]->clientAddr;

//		   clientInfo->hClientSocket= clientInfoArr[nclients]->hClientSocket;

           clientInfo->clientAddr= clientAddr;

           clientInfo->hClientSocket = hClientSocket;

           cout << "Client connected from " << inet_ntoa( clientAddr . sin_addr ) << endl ;

		   cout<<nclients<<"\n";

 

            // Start the client thread

		  // for(int i=0;i<nclients;i++)

		   //{

            hClientThread = CreateThread( NULL, 0,

                ( LPTHREAD_START_ROUTINE ) ClientThread,

                ( LPVOID ) clientInfo, 0, &dwThreadId ) ;

			

            if ( hClientThread == NULL )

            {

                cout << "Unable to create client thread" << endl ;

            }

            else

            {

                //CloseHandle( hClientThread ) ;

            }

			WaitForSingleObject(hClientThread,INFINITE);

		  // }

 

			nclients++;

        

    }

 

    closesocket( hServerSocket ) ;

    WSACleanup( ) ;

    return 0 ;

}

 

bool InitWinSock2_0( )

{

    WSADATA wsaData ;

    WORD wVersion = MAKEWORD( 2, 0 ) ;

 

    if ( ! WSAStartup( wVersion, &wsaData ) )

        return true ;

 

    return false ;

}

 

int ClientThread(LPVOID lpData)

{

	

	//struct CLIENT_INFO* pclientInfo;

	// struct CLIENT_INFO* pclientInfo = new CLIENT_INFO ;

 

    CLIENT_INFO ClientInfo;

	CLIENT_INFO *pClientInfo = &ClientInfo;

	ClientInfo.hClientSocket = (( CLIENT_INFO * ) lpData)->hClientSocket ;

	ClientInfo.clientAddr = (( CLIENT_INFO * ) lpData)->clientAddr;
 
 

     char szBuffer[ 1024 ] ;

     int nLength ;

 

    while ( 1 )

    {

        nLength = recv( pClientInfo -> hClientSocket, szBuffer, sizeof( szBuffer ), 0 ) ;

		cout<<pClientInfo -> hClientSocket<<"\n";

		cout<<nLength<<"\n";

		

        if ( nLength > 0 )

        {

            szBuffer[ nLength ] = '\0' ;

            cout << "Received " << szBuffer << " from " << inet_ntoa( pClientInfo -> clientAddr . sin_addr ) << endl ;

 

            // Convert the string to upper case and send it back, if its not QUIT

           // strupr( szBuffer ) ;

            if ( strcmp( szBuffer, "QUIT" ) == 0 )

            {

                closesocket( pClientInfo -> hClientSocket ) ;

                return 0 ;

            }

            // send( ) may not be able to send the complete data in one go.

            // So try sending the data in multiple requests

            int nCntSend = 0 ;

             

            char *pBuffer = szBuffer ;

 

            while ( ( nCntSend = send( pClientInfo -> hClientSocket, pBuffer, nLength, 0 ) != nLength ) )

            {

                if ( nCntSend == -1 )

                {

                    cout << "Error sending the data to " << inet_ntoa( pClientInfo -> clientAddr . sin_addr ) << endl ;

                    break ;

                }

                if ( nCntSend == nLength )

                    break ;

 

                pBuffer += nCntSend ;

                nLength -= nCntSend ;

            }

        }

        else

        {

            cout << "Error reading the data from " << inet_ntoa( pClientInfo ->clientAddr . sin_addr ) << endl ;

			break;

 

        }

		closesocket(ClientInfo.hClientSocket);

    }

 

    

 

    return 0 ;

}

Open in new window

0
 

Author Comment

by:njoy143
ID: 20337506
Alex,
Thanks for your help, I am  working on the project and going succesfully ahead.
Thanks you once again..
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Months ago my boss came to me with a simple request, “How can we minimize GoTo meeting accounts and also improve our integration and collaboration initiatives?”  Well the answer, with some research, was easy… Lync.  Lync provided us all the necessar…
Article by: Ahmedn1
Introduction Some developers today tend to use Skypekit in their applications to make it more interactive with the user. Skype API is very awesome indeed but the problem is it is only available in C++, Java and Python. I can't understand why Micr…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now