Sunday, April 29, 2012

MultiThreaded server in c++ and win32 api

A very simple server that's show how to apply the windows CreateThread function, follows the normal procedure in creating a server,
  • Initialization of the DLL
  • create socket
  • bind the socket
  • listen for an incoming connection

But the only change was that once its within the while loop, continuously accept incoming connection, then create a thread for the every connection it makes.

The CreateThread takes 6 arguments, but assigned only the function you want to run within that thread, argument of that function, and one optional argument i added for the thread id.

  • recvNsend - Function i want to run with in the thread
  • (LPVOID)clntSocket - parameter it takes in, that is the accecpted client,

The function has to be separately implemented and it always takes LPVOID paramenter, VOID POINTER, i believe. And can be casted when used.


#define _WIN32_WINNT 0x501

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif



#include <windows.h>
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>

#pragma comment(lib, "ws2_32.lib")
#define PORT "4444"
#define BUFFER 1024

using namespace std;

DWORD WINAPI recvNsend(LPVOID lpParam);

struct addrinfo *result, *ptr, hints;
SOCKET servSocket;
SOCKET clntSocket;

void callWsDll()
{
    WSADATA wsadata;
    int iResult;
    iResult = WSAStartup(MAKEWORD(2,2), &wsadata);

    if(iResult != 0)
    {
        cout << "WSAStartup or Calling the socket DLL fail" << endl;
    }
}

int createNconnect()
{
    int iResult;
    DWORD thread;

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family   = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags    = AI_PASSIVE;

    iResult = getaddrinfo(NULL, PORT, &hints, &result);
    if(iResult != 0)
    {
        cout << "getaddrinfo failed " << endl;
        WSACleanup();
    }

    ptr = result;

    servSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
    if(servSocket == INVALID_SOCKET)
    {
        cout << "socket creation failed " << WSAGetLastError() << endl;
        freeaddrinfo(result);
        WSACleanup();
        return 1;
    }

    iResult = bind(servSocket, ptr->ai_addr, ptr->ai_addrlen);
    if(iResult == SOCKET_ERROR)
    {
        cout << "socket binding failed " << WSAGetLastError() << endl;
        freeaddrinfo(result);
        WSACleanup();
        return 1;
    }
    freeaddrinfo(ptr);
    freeaddrinfo(result);

    iResult = listen(servSocket, SOMAXCONN);
    if(iResult == SOCKET_ERROR)
    {
        cout << "listening failed " << WSAGetLastError() << endl;
        closesocket(servSocket);
        WSACleanup();
        return 1;
    }
    while(true)
    {
        clntSocket = accept(servSocket, NULL, NULL);
        if(clntSocket == INVALID_SOCKET)
        {
            cout << "accepting clients failed " << WSAGetLastError() <<endl;
            closesocket(servSocket);
            WSACleanup();
            return 1;
        }
        CreateThread(NULL, 0, recvNsend, (LPVOID)clntSocket, 0, &thread);
        cout << thread << endl;
    }
    closesocket(servSocket);

    return iResult;
}

DWORD WINAPI recvNsend(LPVOID lpParam)
{
   int iResult;
   int iSresult;
   char rcvbuffer[BUFFER];
   SOCKET rsclientSocket = (SOCKET)lpParam;

   do{
       iResult = recv(rsclientSocket, rcvbuffer, BUFFER, 0);
       if(iResult > 0)
       {
           cout << "Bytes recieved " << iResult << endl;
           iSresult = send(rsclientSocket, rcvbuffer, iResult, 0);
           if(iSresult == SOCKET_ERROR)
           {
               cout << "send failed" << WSAGetLastError() << endl;
               closesocket(rsclientSocket);
               WSACleanup();
               return 1;
           }
           cout << "Bytes sent " << iSresult << endl;

       }
       else if(iResult == 0)
       {
           cout << "Connection closed ...." << endl;
       }
       else
       {
           cout << "Recieving message failed " << WSAGetLastError() << endl;
           closesocket(rsclientSocket);
           WSACleanup();
           return 1;
       }
   }while(iResult > 0);
   return 0;
}

int shutdownSocket(SOCKET &anysock)
{
    int iResult;
    iResult = shutdown(anysock, SD_SEND);
    if(iResult == SOCKET_ERROR)
    {
        cout << "shutdown failed" << WSAGetLastError() << endl;
        closesocket(anysock);
        WSACleanup();
        return 1;
    }
    closesocket(anysock);
    WSACleanup();

    return 0;
}




No comments:

Post a Comment

How to create Custom push button in QT5

To be honest this is not my work its an exact copy from this link. http://mcmtechtips.blogspot.com/2012/03/shape-qpushbutton-in-your-own-st...