Thread: TCP Server

  1. #1
    Registered User
    Join Date
    Mar 2011
    Posts
    69

    TCP Server

    Hello, i have written a simple TCP server. But when i tried make it multithreaded i screw up something. Can someone help me to find out what's wrong with it?

    Code:
    #include <cstdlib>
    #include <iostream>
    #include <winsock2.h>
    #include <ws2tcpip.h>
    
    //Zmienne stale
    #define DEFAULT_BUFLEN 512
    #define MAX_CLIENTS 100
    
    using namespace std;
    
    //Deklaracja funkcji
    DWORD WINAPI ServeClient(LPVOID lpParam);
    
    //Zmienne globalne
    typedef struct TThreadInfo {
        int ID;
        int cos1;
    } TTHREADINFO, *PTTHREADINFO;
    
    char *D_PORT = "6698";
    bool ShutDown = 0;
    HANDLE ClientThread [MAX_CLIENTS];
    HANDLE ListenerHandle;
    DWORD ClientThreadID [MAX_CLIENTS];
    WSADATA wsaData;
    SOCKET ListenSocket = INVALID_SOCKET;
    SOCKET ClientSocket = INVALID_SOCKET;
    
    struct addrinfo *result = NULL;
    struct addrinfo *ptr = NULL;
    struct addrinfo hints;
    
    //Rest
    bool StartWSA(void)
    {
         if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) return 0; else return 1;
    }
    
    bool InitSock(void)
    {
         ZeroMemory(&hints, sizeof (hints));
         hints.ai_family = AF_INET;
         hints.ai_socktype = SOCK_STREAM;
         hints.ai_protocol = IPPROTO_TCP;
         hints.ai_flags = AI_PASSIVE;
         // Resolve the local address and port to be used by the server
         if ((getaddrinfo(NULL, D_PORT, &hints, &result)) != 0) return 0; else return 1;   
    }
    
    bool CreateSock(void)
    {
         // Create a SOCKET for the server to listen for client connections
         ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
         if (ListenSocket == INVALID_SOCKET) return 0; else return 1;
         //
        // for(int a=0;a<MAX_CLIENTS;a++) ClientSocket[a] = INVALID_SOCKET;
    }
    
    bool BindSock(void)
    {
         // Setup the TCP listening socket
         int _result;
         _result = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
         if (_result == SOCKET_ERROR) return 0; else return 1;
    }
    
    bool Listener(void)
    {
         if ( listen( ListenSocket, SOMAXCONN ) == SOCKET_ERROR ) return 0; else return 1;
    }
    
    DWORD WINAPI ServeClient(LPVOID lpParam)
    {      
          printf("Serving client..");
          bool CloseConnection = 0;
          char recvbuf[DEFAULT_BUFLEN];
          int sResult, cResult;
          int recvbuflen = DEFAULT_BUFLEN;
          SOCKET current_sock;
          current_sock = (SOCKET)lpParam;
          do {
          cResult = recv(current_sock, recvbuf, recvbuflen, 0);
          if (cResult > 0) {
            printf("Bytes received: %d\n", cResult);
    
            // Echo the buffer back to the sender
            sResult = send(current_sock, recvbuf, cResult, 0);
            if (sResult == SOCKET_ERROR) {
                printf("send failed: %d\n", WSAGetLastError());
                closesocket(current_sock);
                WSACleanup();
                CloseConnection = 1;
                return 1;
            }
            printf("Bytes sent: %d\n", sResult);
          } else {
            printf("Connection error..");
            closesocket(current_sock);
            WSACleanup();
            CloseConnection = 1;
            return 1;
        }
      } while (!CloseConnection); 
    }
    
    int main(int argc, char *argv[])
    {
        if (argv[1] != 0) D_PORT = argv[1];
        if (!StartWSA()) 
        {
           printf("- WSA Startup error\n"); 
           system("PAUSE");
           return 1; 
        }
        printf("* WSA started\n");
        
        if (!InitSock()) 
        {
            printf("- GetAddrInfo failed\n");
            WSACleanup();
            system("PAUSE");
            return 1;
        }
        printf("* Socket initialized\n");
    
        if (!CreateSock())
        {
            printf("- Error at socket\n");
            freeaddrinfo(result);
            WSACleanup();
            system("PAUSE");
            return 1;
        }
        printf("* Socket created\n");
        
        if (!BindSock())
        {
            printf("- Bind failed\n");
            freeaddrinfo(result);
            closesocket(ListenSocket);
            WSACleanup();
            system("PAUSE");
            return 1;
        }
        printf("* Binging socket success\n");
        
        if (!Listener())
        {
            printf("- Listen failed\n");
            closesocket(ListenSocket);
            WSACleanup();
            system("PAUSE");
            return 1;
        }
        printf("* Listener started\n");
        printf("* Server is running :\n");
        printf("  - IP : 127.0.0.1\n");
        printf("  - PORT : %s\n", D_PORT);
    
    do
      {
          ClientSocket = accept(ListenSocket, NULL, NULL);
          if (ClientSocket == INVALID_SOCKET) {
            printf("Client connection failed\n");
            // closesocket(ListenSocket);
            //WSACleanup();        
            }  
          printf("Client connected");
          
          DWORD thread;
          CreateThread(
            NULL,                        // no security attributes 
            0,                           // use default stack size  
            ServeClient,                  // thread function 
            (LPVOID)ClientSocket,                // argument to thread function 
            0,                           // use default creation flags 
            &thread);
          ClientSocket = INVALID_SOCKET;
      }
      while (true);
    
        system("PAUSE");
        closesocket(ListenSocket);
        WSACleanup();
        return EXIT_SUCCESS;
    }
    The thing happen is that im getting in infinite loop here :

    Code:
    do
      {
          ClientSocket = accept(ListenSocket, NULL, NULL);
          if (ClientSocket == INVALID_SOCKET) {
            printf("Client connection failed\n");
            // closesocket(ListenSocket);
            //WSACleanup();        
            }  
          printf("Client connected");
          
          DWORD thread;
          CreateThread(
            NULL,                        // no security attributes 
            0,                           // use default stack size  
            ServeClient,                  // thread function 
            (LPVOID)ClientSocket,                // argument to thread function 
            0,                           // use default creation flags 
            &thread);
          ClientSocket = INVALID_SOCKET;
      }
      while (true);
    Why it's not waiting for next connection and getting old one?

  2. #2
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    When the client closes the connection recv will return 0. You should not be treating that as an error condition and subsequently cleaning up Winsock via WSACleanup.

  3. #3
    Registered User
    Join Date
    Mar 2011
    Posts
    69
    Oh yea i completly forgot i've changed this. It works now, thanks.

    One more question how do i get IP, like i want to know client's ip who connected?
    Last edited by kargo; 03-07-2011 at 11:47 AM.

  4. #4
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    instead of calling accept like this:
    Code:
    ClientSocket = accept(ListenSocket, NULL, NULL);
    try passing it a sockaddr_in struct and its length for it to fill with the client info.

    accept() winsock reference

  5. #5
    Registered User
    Join Date
    Mar 2011
    Posts
    69
    Thanks it works this way
    Code:
    struct sockaddr_in clientinfo;
    int cilen = sizeof(struct sockaddr);
    ClientSocket = accept(ListenSocket, (LPSOCKADDR)&clientinfo, &cilen);
    printf(inet_ntoa(clientinfo.sin_addr));

  6. #6
    Registered User
    Join Date
    Mar 2011
    Posts
    69
    One more question, sometimes when i try send two packets, server interprets it as one packet like :

    1 - I send byte 0x01
    2 - I send buff with text (0x5A3D7C....)

    The server interprets it as one : 015A3D7C..
    So i do something wrong or it is how it works? In delphi i hadn't that problem, everytime i got separated packets.

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    That's how TCP streams work.
    You get guaranteed transmission of the bytes in the order you sent them.

    A typical TCP stream sends either 'length' bytes, or uses a record separator (like newline) to mark boundaries in the information stream.
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. TCP Server cannot save buffer data to mysql !
    By syedmuhd in forum C Programming
    Replies: 5
    Last Post: 09-18-2010, 08:54 PM
  2. Windows TCP Server Can't Handle >100 Clients
    By Xterria in forum Networking/Device Communication
    Replies: 13
    Last Post: 11-02-2009, 07:21 PM
  3. constantly reading and writing to a tcp server
    By liri in forum Networking/Device Communication
    Replies: 4
    Last Post: 01-22-2008, 08:57 AM
  4. TCP Sockets: multiple clients - one server
    By Printisor in forum C Programming
    Replies: 4
    Last Post: 11-01-2007, 10:34 AM
  5. socket question
    By Unregistered in forum C Programming
    Replies: 3
    Last Post: 07-19-2002, 01:54 PM