Thread: Simple c++ socket server game needs client

  1. #1
    Registered User
    Join Date
    Mar 2012
    Posts
    34

    Simple c++ socket server game needs client

    Hello, i found this socket server and has no client created to it
    i try to edit client for it.. it connect and server reads that:
    Code:
            xmen90s Non-Blocking Multi-Client Echo Server for Dungeon Siege
     
     SOCKET ESTABLISHED
     Binding socket:0
     Socket Bound to port : 1200
     ACCEPTING CLIENT to array position [0] with IP ADDRESS 192.168.1.5
    when open the client it connect to server with message:
    Code:
     Name: pc5
     Address: 192.168.1.5
     Name: pc5
     Address: 192.168.1.5
     --------------- Summary of socket settings -------------------
        Socket Id:     108
        port #:        1200
        debug:         false
        reuse addr:    false
        keep alive:    false
        send buf size: 8192
        recv bug size: 8192
        blocking:      true
        linger on:     true
        linger seconds: 10
     ----------- End of Summary of socket settings ----------------
     connecting to the server [pc5] ...
     [pc5:SEND]
    when type specific commands that sever must receive it like (~1, ~2) nothing happens
    Also when closing the server or client nothing happens too

    anyone could help please?

    this is Server.cpp
    Code:
     // COMMENTS //
    
    //    Author    :    xmen90s -> based on the tutorial of Aaron aka FireNet
    //                [email protected]
    
    //    Date    :    June 10th of 2004
    
    //    Purpose    :    This server receives input from multiple clients and keeps
    //                a RAM database of a few pieces of information like screen
    //                name, character model, and position
    //                The server then will echo back information to all clients
    //                instructing them on where to move actors
    
    //                Essentially I'm working on rebuilding the multiplayer system
    //                of a game called Dungeon Siege from ground up.
    
    //    I want to put a special thanks out to Aaron aka FireNet for writing
    //    the most excellent tutorial I have ever read.  I went from knowing
    //    cin and cout to writing a full non-blocking multi-client echo server
    //    in just one and a half weeks because of him.
    
    // LINKS //
    
    //    Remember to link to : wsock32.lib
    
     // INCLUDE FILES //
     #define _WIN32_WINNT 0x0400
     
     #include <fstream.h>
     #include <iostream.h>
     #include <stdio.h>
     #include <string.h>
     #include <winsock.h>
     
     // DEFINITIONS //
     
     #define        PORT 1200        // Define the port to connect to
     #define        MAX_CLIENTS 10    // Define the maximum number of clients we can receive
     #define        BUFFER_SIZE 256 // Define the buffer size of the messages
     
     // STRUCTURES //
     
     struct _client
     {
         bool        connected;
         sockaddr_in    address;
         SOCKET        socket;
         fd_set        socket_data;
         int            address_length;
     
         char        template_name[15];
         char        screen_name[15];
         char        siegepos[45];
     };
     
     // GLOBAL VARIABLES //
     
     sockaddr_in    server_address;
     sockaddr    server_socket_address;
     SOCKET        server_socket;
     
     _client        client[MAX_CLIENTS];
     int            clients_connected = 0;
     
     // FUNCTION DECLARATIONS //
     
     bool    accept_client ( _client *current_client );
     int        accept_connections ();
     int        disconnect_client ( _client *current_client );
     void    echo_message ( char *message );
     void    end_server();
     void    midcopy ( char* input, char* output, int start_pos, int stop_pos );
     int        receive_client ( _client *current_client, char *buffer, int size );
     void    receive_data();
     int        send_data ( _client *current_client, char *buffer, int size );
     void    start_server();
     
     // FUNCTION DEFINITIONS //
     
     bool accept_client ( _client *current_client )
     {
         // Accept incoming connections
         current_client->address_length = sizeof ( sockaddr );
         current_client->socket = accept ( server_socket, ( sockaddr * )  &current_client->address, &current_client->address_length  );
     
         if ( current_client->socket == 0 )
         {
             // No data in socket
             return ( FALSE );
         }
         else if ( current_client->socket == SOCKET_ERROR )
         {
             // Socket error
             return ( FALSE );
         }
         else
         {
             // Occupy the client slot
             current_client->connected = TRUE;
             FD_ZERO ( &current_client->socket_data );
             FD_SET ( current_client->socket, &current_client->socket_data );
     
             return ( TRUE );
         }
     
         return ( FALSE );
     }
     
     int accept_connections()
     {
         if ( clients_connected < MAX_CLIENTS )
         {
             for ( int j = 0; j < MAX_CLIENTS; j++ )
             {
                 if ( !client[j].connected )
                 {
                     if ( accept_client ( &client[j] ) )
                     {
                         // Increment the client count
                         clients_connected++;
     
                         // Grab the ip address of the client ... just for fun
                         char *client_ip_address = inet_ntoa ( client[j].address.sin_addr );
     
                         // Output connection
                         cout << "ACCEPTING CLIENT to array position ["  << j << "] with IP ADDRESS " << client_ip_address  << endl;
                     }
                 }
             }
         }
     
         return ( 1 );
     }
     
     int disconnect_client ( _client *current_client )
     { // Disconnect a client
         if ( current_client->connected == TRUE )
         { // Close the socket for the client
             closesocket ( current_client->socket );
         }
     
         // Set the new client state
         current_client->connected = FALSE;
     
         // Clear the address length
         current_client->address_length = -1;
     
         // Decrement the current number of connected clients
         clients_connected--;
     
         // Declare a variable to store the disconnect message into
         char raw_data[BUFFER_SIZE];
     
         // Parse in the client data to send
         sprintf ( raw_data, "~4 %s", current_client->screen_name );
     
         // Echo out the disconnect message so all clients drop this client
         echo_message ( raw_data );
     
         cout << "Disconnecting client[]" << endl;
     
         return ( 1 );
     }
     
     void echo_message ( char *message )
     {
         for ( int j = 0; j < MAX_CLIENTS; j++ )
         {
             if ( client[j].connected )
             { // Echo the message to all clients
                 send_data ( &client[j], message, BUFFER_SIZE );
             }
         }
     }
     
     void end_server()
     { // Shut down the server by disconnecting all clients and clearing winsock
         // Disconnect all clients
         for ( int j = 0; j < MAX_CLIENTS, j++;) { disconnect_client ( &client[j] ); }
     
         // Close the listening socket for the server
         closesocket ( server_socket );
     
         // Clean up winsock
         WSACleanup();
     }
     
     void midcopy ( char* input, char* output, int start_pos, int stop_pos )
     {
         int index = 0;
     
         for ( int i = start_pos; i < stop_pos; i++ )
         {
             output[index] = input[i];
             index++;
         }
     
         output[index] = 0;
     }
     
     int receive_client ( _client *current_client, char *buffer, int size )
     {
         if ( FD_ISSET ( current_client->socket, &current_client->socket_data ) )
         {
             // Store the return data of what we have sent
             current_client->address_length = recv ( current_client->socket, buffer, size, 0 );
     
             if ( current_client->address_length == 0 )
             { // Data error on client
                 disconnect_client ( current_client );
     
                 return ( FALSE );
             }
     
             return ( TRUE );
         }
     
         return ( FALSE );
     }
     
     void receive_data()
     {
         char buffer[BUFFER_SIZE];
     
         for ( int j = 0; j < MAX_CLIENTS; j++ )
         {
             if ( client[j].connected )
             {
                 if ( receive_client ( &client[j], buffer, BUFFER_SIZE ) )
                 {
                     if ( buffer[0] == '~' )
                     { // All data should be buffered by a '~' just because
     
                         if ( buffer[1] == '1' ) // Add Client Command
                         {
                             // Declare the buffer to store new client information into
                             char raw_data[BUFFER_SIZE];
     
                             // Parse out the 'Add Client' command
                             midcopy ( buffer, raw_data, 3, strlen ( buffer ) );
     
                             // Store the client information into our RAM client database
                             sscanf ( raw_data, "%s %s %s", client[j].template_name, client[j].screen_name, client[j].siegepos );
     
                             for ( int k = 0; k < MAX_CLIENTS; k++ )
                             {
                                 if ( ( client[k].connected ) && ( j != k ) )
                                 {
                                     // Parse in the client data to send
                                     sprintf ( raw_data, "~1 %s %s %s",  client[k].template_name, client[k].screen_name, client[k].siegepos );
     
                                     // Send the client data
                                     send_data ( &client[j], raw_data, BUFFER_SIZE );
                                 }
                             }
                         }
                         else if ( buffer[1] == '2' ) // Move Client Command
                         {
                             // Declare the buffer to store new client information into
                             char raw_data[BUFFER_SIZE];
     
                             // Parse out the 'Move Client' command
                             midcopy ( buffer, raw_data, 3, strlen ( buffer ) );
     
                             // Update the client information into our RAM client database
                             sscanf ( raw_data, "%s %s", client[j].screen_name, client[j].siegepos );
                         }
                         else if ( buffer[1] == '3' ) // Chat Client Command
                         {
                             // ECHO THE MESSAGE BACK TO ALL CLIENTS
                         }
                         else if ( buffer[1] == '4' ) // Remove Client Command
                         {
                             // Disconnect the current client
                             disconnect_client ( &client[j] );
                         }
     
                         // Display all data received
                         // cout << buffer << endl;
     
                         // Echo the message to the other clients
                         echo_message ( buffer );
     
                         // Clear the buffer
                         buffer[0] = '/0';
                     }
                 }
             }
         }
     }
     
     int send_data ( _client *current_client, char *buffer, int size )
     {
         // Store the return information about the sending
         current_client->address_length = send ( current_client->socket, buffer, size, 0 );
     
         if ( ( current_client->address_length == SOCKET_ERROR ) || ( current_client->address_length == 0 ) )
         { // Check for errors while sending
             disconnect_client ( current_client );
     
             return ( FALSE );
         }
         else return ( TRUE );
     }
     
     void start_server()
     { // Initialize the server and start listening for clients
         // LOCAL VARIABLES //
         WSADATA wsaData;
         int res, i = 1;
     
         // Set up the address structure
         server_address.sin_family = AF_INET;
         server_address.sin_addr.s_addr = INADDR_ANY;
         server_address.sin_port = htons ( PORT);
     
         // IM GUESSING : Copy over some addresses, conversions of some sort ?
         memcpy ( &server_socket_address, &server_address, sizeof ( SOCKADDR_IN ) );
     
         res = WSAStartup ( MAKEWORD ( 1, 1 ), &wsaData );
     
         // Start winsock
         if ( res != 0 ) 
         {
             cout << "WSADATA ERROR : Error while attempting to initialize winsock." << endl;
         }
     
         // Create a listening socket for the server
         server_socket = socket ( AF_INET, SOCK_STREAM, IPPROTO_TCP );
     
         if ( server_socket == INVALID_SOCKET )
         {
             cout << "SOCKET ERROR : Invalid socket." << endl;
         }
         else if ( server_socket == SOCKET_ERROR )
         {
             cout << "SOCKET ERROR : Socket error." << endl;
         }
         else
         {
             cout << "SOCKET ESTABLISHED" << endl;
         }
     
         // Sets the option to re-use the address the entire run of the program
         setsockopt ( server_socket, SOL_SOCKET, SO_REUSEADDR, ( char * ) &i, sizeof ( i ) );
     
         // Bind the socket to the address
         res = bind ( server_socket, &server_socket_address, sizeof ( server_socket_address ) );
     
         cout << "Binding socket:" << res << endl;
     
         if ( res != 0 )
         {
             cout << "BINDING ERROR : Failed to bind socket to address." << endl;
         }
         else
         {
             cout << "Socket Bound to port : "<< PORT << endl;
         }
     
         // Start listening for connection requests
         res = listen ( server_socket, 8 );
     
         // This makes the server non blocking, hence it won't wait for a response
         unsigned long b = 1;
         ioctlsocket ( server_socket, FIONBIO, &b );
     
         // Clear all clients state
         for ( int j = 0; j < MAX_CLIENTS; j++ ) { client[j].connected = FALSE; }
     }
     
     ////////////////////////////////////////////////////////////////////////////
     ////////////////////////////////////////////////////////////////////////////
     
     // MAIN FUNCTION //
     
     int main()
     {
         cout << "\txmen90s Non-Blocking Multi-Client Echo Server for Dungeon Siege\n" << endl;
     
         // Initialize winsock and start listening
         start_server();
     
         // Loop forever
         bool looping = TRUE;
     
         while ( looping )
         {
             // Accept all incoming client connections
             accept_connections();
     
             // Receive all data from clients
             receive_data();
         }
     
         // Shut down winsock
         end_server();
     
         return 0;
     }

    &And this is client.cpp
    Code:
     #include "..\mySocket\mySocket.h"
     #include "..\myLog\myLog.h"
     #include "..\myException\myException.h"
     #include "..\myHostInfo\myHostInfo.h"
     
     myLog winLog;
     string serverIPAddress = "";
     
     void readServerConfig();
     void checkFileExistence(const string&);
     
     int main()
     {
     
     #ifdef WINDOWS_XP
     
         // Initialize the winsock library
         WSADATA wsaData;
         winLog << "system started ..." << endl;
         winLog << endl << "initialize the winsock library ... ";
     
         try 
         {
             if (WSAStartup(0x101, &wsaData))
             {
                 myException* initializationException = new myException(0,"Error: calling WSAStartup()");
                 throw initializationException;
             }
         }
         catch(myException* excp)
         {
             excp->response();
             delete excp;
             exit(1);
         }
         winLog << "successful" << endl;
     
     #endif
             
         // get local information if neither the name or the address is given
     
         winLog << endl;
         winLog << "Retrieve the localHost [CLIENT] name and address:" << endl;
         
         myHostInfo uHostAddress;
         string localHostName = uHostAddress.getHostName();
         string localHostAddr = uHostAddress.getHostIPAddress();
         cout << "Name: " << localHostName << endl;
         cout << "Address: " << localHostAddr << endl;
         winLog << "        ==> Name: " << localHostName << endl;
         winLog << "        ==> Address: " << localHostAddr << endl;
     
         // get server's information
     
         readServerConfig();
         winLog << endl;
         winLog << "Retrieve the remoteHost [SERVER] name and address:" << endl;
         winLog << "        ==> the given address is " << serverIPAddress << endl;
     
         myHostInfo serverInfo(serverIPAddress,ADDRESS);
         string serverName = serverInfo.getHostName();
         string serverAddr = serverInfo.getHostIPAddress();
         cout << "Name: " << serverName << endl;
         cout << "Address: " << serverAddr << endl;
         winLog << "        ==> Name: " << serverName << endl;
         winLog << "        ==> Address: " << serverAddr << endl;
     
         // an instance of the myTcpSocket is created.  At this point a TCP 
         // socket has been created and a port has been defined.
         myTcpSocket myClient(PORTNUM);
         myClient.setLingerOnOff(true);
         myClient.setLingerSeconds(10);
     
         cout << myClient;
         winLog << "client configuation: " << endl;
         winLog << myClient;
     
         // connect to the server.
         cout   << "connecting to the server [" << serverName << "] ... " << endl;
         winLog << "connecting to the server [" << serverName << "] ... " << endl;
         myClient.connectToServer(serverAddr,ADDRESS);
     
         int recvBytes = 0;
     
         while (1)
         {
             // send message to server
     
             char sendmsg[MAX_MSG_LEN+1];
             memset(sendmsg,0,sizeof(sendmsg));
             cout << "[" << localHostName << ":SEND] ";
             cin.getline(sendmsg,MAX_MSG_LEN);
     
             string sendMsg(sendmsg);
             if ( sendMsg.compare("Bye") == 0 || sendMsg.compare("bye") == 0 ) break;
     
             //cout   << "[" << localHostName << ": SEND] " << sendMsg << endl;
             winLog << "[" << localHostName << ": SEND] " << sendMsg << endl;
             myClient.sendMessage(sendMsg);
     
             // receive message from server
     
             string clientMessageIn = "";
             recvBytes = myClient.recieveMessage(clientMessageIn);
             if ( recvBytes == -99 ) break;
     
             cout   << "[RECV:" << serverName << "]: " << clientMessageIn << endl;
             winLog << "[RECV:" << serverName << "]: " << clientMessageIn << endl;
     
         }
     
     #ifdef WINDOWS_XP
     
         // Close the winsock library
         winLog << endl << "system shut down ...";        
         
         try 
         {
             if (WSACleanup())
             {
                 myException* cleanupException = new myException(0,"Error: calling WSACleanup()");
                 throw cleanupException;
             }
         }
         catch(myException* excp)
         {
             excp->response();
             delete excp;
             exit(1);
         }
         winLog << "successful" << endl;
     
     #endif
     
         return 1;
     }
     
     void readServerConfig()
     {
         string serverConfigFile = "serverConfig.txt";    
         checkFileExistence(serverConfigFile);
         ifstream serverConfig(serverConfigFile.c_str());
     
         // read server's IP address
         getline(serverConfig,serverIPAddress);
         //istrstream In(inLine.c_str());
         //In >> serverIPAddress;
     
         serverConfig.close();
     }
     
     void checkFileExistence(const string& fileName)
     {
         ifstream file(fileName.c_str());
         if (!file) 
         {
             cout << "Cannot continue:" << fileName << " does NOT exist!" << endl;
             exit(1);
         }
         file.close();
     }
    Last edited by bakri; 05-10-2012 at 07:49 AM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    It's a shame you copied so much code that is so badly broken - oh well.

    In end_server()
    > for ( int j = 0; j < MAX_CLIENTS, j++;)
    Look up what the comma operator does - it isn't what you think.

    It should be
    for ( int j = 0; j < MAX_CLIENTS ; j++ )

    > // Clear the buffer
    > buffer[0] = '/0';
    Guess again. This is a wide character, quite dissimilar to '\0'.

    > // Store the return data of what we have sent
    > current_client->address_length = recv ( current_client->socket, buffer, size, 0 );
    ..
    > // Store the return information about the sending
    > current_client->address_length = send ( current_client->socket, buffer, size, 0 );
    The thing about send() and recv() is that neither GUARANTEES to transfer the whole message in a single call (for TCP connections).
    If you try to send "hello world\n", then it's perfectly valid (and correct) for send to only manage "hello w" before returning, and recv() to only get as far as "hell" before returning as well.
    In both cases, you need to check the return result to see if the whole message has been sent, and if necessary call the function again.

    Eg.
    Code:
    do {
        int n = send ( socket, buffer, size, 0 );
        if ( n > 0 ) {
            // some kind of success
            buffer += n;  // adjust buffer and size for the amount sent
            size -= n;
        } else
        if ( n == 0 ) {
            // remote disconnect, bail
            break;
        } else {
            // an error?
            if ( errno == EAGAIN ) {
                // non-blocking socket temporarily busy, sleep and try again?
            } else {
            }
        }
    } while ( size > 0 );
    The same applies for recv(), except you need to examine the message stream to decide when a complete "message" has arrived.
    Perhaps it has say "\n" as a message separator.

    The other thing about recv() is that it does NOT append a \0 onto your buffer to make it a proper C string.
    Further, if you have
    char buff[BUFFER_SIZE];
    n = recv( sock, buff, BUFFER_SIZE, 0 );

    then if recv() completely fills the buffer, then there is no room to append a \0 (or pre-fill the buffer with \0).
    Always allow room for the \0, if you intend to use str... functions later on (and not just use the received length result from recv).


    > // Parse in the client data to send
    > sprintf ( raw_data, "~1 %s %s %s", client[k].template_name, client[k].screen_name, client[k].siegepos );
    > // Send the client data
    > send_data ( &client[j], raw_data, BUFFER_SIZE );
    Try sending strlen(raw_data) instead of BUFFER_SIZE.
    Then you'll only send the actual string, and not all the garbage in the char array that follows it.
    See above about introducing meaningful record separators between messages.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Mar 2012
    Posts
    34
    thanx allot.. it's going nice
    it work on my pc..

    when i copy it to another pc and added the port to my firewall can't connect to server...
    i want it work over internet

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Socket ( server client Get pid )
    By Syd in forum C Programming
    Replies: 0
    Last Post: 02-15-2011, 08:00 AM
  2. C-Windows-Socket-(Client/Server)
    By EyesOnly in forum Networking/Device Communication
    Replies: 3
    Last Post: 08-06-2009, 11:12 AM
  3. Problem with simple socket client/server program
    By spencer88 in forum C Programming
    Replies: 6
    Last Post: 05-05-2009, 11:05 PM
  4. Looking for coder: Simple C++ Client / Server game
    By kocho in forum Projects and Job Recruitment
    Replies: 1
    Last Post: 02-04-2006, 02:34 PM
  5. Code for Client/Server Socket
    By Unregistered in forum C++ Programming
    Replies: 4
    Last Post: 01-15-2002, 09:30 AM