Code:

Hi guys, before we start I'm going to assume you know how to create single threaded servers, and have a basic knowledge of Winsock and what threads are... Now it really isn't that hard to create multi-threaded servers once you get used to them... So firstly I'm going to show you a basic single threaded server, then I'll show you how to upgrade it to a multi-threaded server, but first a bit of Questions and Answers is in order ...

Q. What are the benefits of using a multi-threaded server over a single threaded server?
A. A multi-threaded server allows you to have more than 1 client connected at any one time,
at some point you may want to create a game server or other, you will find that you need to
be able to handle multiple connections, threads are a solution to handling multiple clients.

Hm ok i couldn't think of any more questions... So if you have any let me know and I'll answer them and merge them into this topic ...

Right below is the code to a very basic single threaded Winsock server that I just whipped up:

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <winsock.h>

int main()
{
printf("Starting up TCP server by KOrUPt\r\n");

SOCKET sock;

WSADATA wsaData;
sockaddr_in server;

int ret = WSAStartup(0x101,&wsaData); // use highest version of winsock avaliable

if(ret != 0)
{
    return 0;
}
  
server.sin_family=AF_INET; 
server.sin_addr.s_addr=INADDR_ANY; 
server.sin_port=htons(123); 

sock=socket(AF_INET,SOCK_STREAM,0); 

if(sock == INVALID_SOCKET)
{
    return 0;
}
  
if( bind(sock,(sockaddr*)&server,sizeof(server)) !=0 )
{
    return 0;
}
   
if(listen(sock,5) != 0)
{
    return 0;
}

SOCKET client;
sockaddr_in from;
int fromlen = sizeof(from); 
  
while(true)
{ 
  client = accept(sock,(struct sockaddr*)&from,&fromlen);
  
  // recv/send cmds ...
  
  break;
}

closesocket(sock); 
WSACleanup(); 

return 0;
}

Now that code can only accept one connection at a time, lets modify it so it can accept and handle as many clients as you choose .

This isn't too hard, it's just a case of passing the socket to a thread on each accepted client and calling your recv cmds function from there. Ok, to show you how to do this I'll code a simple example that can accept multiple clients and handle a few basic commands, I'll comment it along the way so you should be able to understand it and code your own for future use . Check the code below 

#include <windows.h>
#include  <stdlib.h>
#include <stdio.h>
#include <winsock.h>

// our thread for recving commands
DWORD WINAPI receive_cmds(LPVOID lpParam) 
{
  printf("thread created\r\n");
  
  // set our socket to the socket passed in as a parameter   
  SOCKET current_client = (SOCKET)lpParam; 
  
  // buffer to hold our recived data
  char buf[100];
  // buffer to hold our sent data
  char sendData[100];
  // for error checking 
  int res;
  
  // our recv loop
  while(true) 
  {
     res = recv(current_client,buf,sizeof(buf),0); // recv cmds
     
     Sleep(10);
     
     if(res == 0)
     {
      MessageBox(0,"error","error",MB_OK);
      closesocket(current_client);
      ExitThread(0);
     }
     
     if(strstr(buf,"hello"))
     { // greet this user
       printf("\nrecived hello cmd");
       
       strcpy(sendData,"hello, greetz from KOrUPt\n");
       Sleep(10);
       send(current_client,sendData,sizeof(sendData),0); 
     }                                
     else if(strstr(buf,"bye"))   
     { // dissconnected this user
       printf("\nrecived bye cmd\n");
       
       strcpy(sendData,"cya\n");
       Sleep(10);
       send(current_client,sendData,sizeof(sendData),0);

      // close the socket associted with this client and end this thread
       closesocket(current_client);
       ExitThread(0);
     }
     else
     {
       strcpy(sendData,"Invalid cmd\n");
       Sleep(10);
       send(current_client,sendData,sizeof(sendData),0);
     }
     
     // clear buffers
       strcpy(sendData,"");
       strcpy(buf,"");
   }
}   

int main()
{
printf("Starting up multi-threaded TCP server by KOrUPt\r\n");

// our masterSocket(socket that listens for connections)
SOCKET sock;

// for our thread
DWORD thread; 

WSADATA wsaData;
sockaddr_in server;

// start winsock
int ret = WSAStartup(0x101,&wsaData); // use highest version of winsock avalible

if(ret != 0)
{
    return 0;
}
  
// fill in winsock struct ... 
server.sin_family=AF_INET; 
server.sin_addr.s_addr=INADDR_ANY; 
server.sin_port=htons(123); // listen on telnet port 23

// create our socket
sock=socket(AF_INET,SOCK_STREAM,0); 

if(sock == INVALID_SOCKET)
{
    return 0;
}
  
// bind our socket to a port(port 123) 
if( bind(sock,(sockaddr*)&server,sizeof(server)) !=0 )
{
    return 0;
}
  
// listen for a connection  
if(listen(sock,5) != 0)
{
    return 0;
}

// socket that we snedzrecv data on
SOCKET client;

sockaddr_in from;
int fromlen = sizeof(from); 
  
// loop forever 
while(true)
{ 
  // accept connections
  client = accept(sock,(struct sockaddr*)&from,&fromlen);
  printf("Client connected\r\n");
  
  // create our recv_cmds thread and parse client socket as a parameter
  CreateThread(NULL, 0,receive_cmds,(LPVOID)client, 0, &thread);  
}

// shutdown winsock
closesocket(sock); 
WSACleanup(); 

// exit
return 0;
}

Well assuming you have a basic understanding of threads and winsock you should be able to follow and understand the above code and hopefully after a bit of experimenting build it into your own server application... I suggest you try and create a basic multi-threaded text file transfer server ... If you have any questions relating to this tutorial reply within this thread or PM me. Hopefully this tutorial helped you out to some degree . Also if you want to test out the server just use the client I built. Client code attached below:

#include <windows.h>
#include <winsock.h>
#include <stdio.h>
#include <iostream.h>
#include <conio.h>
#include <signal.h>
#include <stdio.h>

//DECLARATIONS
    //error trapping signals
      #define SIGINT 2
      #define SIGKILL 9
      #define SIGQUIT 3
    // SOCKETS
      SOCKET sock,client;

void s_handle(int s)
{
    if(sock)
       closesocket(sock);
    if(client)
       closesocket(client);
    WSACleanup();
    Sleep(1000);
    cout<<"EXIT SIGNAL :"<<s;
    exit(0);
}


void s_cl(char *a, int x)
{
    cout<<a;
    s_handle(x+1000);
}


int main()
{
   HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
   SetConsoleTextAttribute(hStdout, FOREGROUND_GREEN|FOREGROUND_INTENSITY);
   SetConsoleTitle(".:: Basic Echo Client By KOrUPt 07 ::. ");
    
    
    //Declarations
    DWORD poll;
    int res,i=1,port=999;
    char buf[100];
    char msg[100] = "";
    char ip[15];
    WSADATA data;
    
    signal(SIGINT,s_handle);
    signal(SIGKILL,s_handle);
    signal(SIGQUIT,s_handle);
    
    cout<<"\t\tEcho Client by KOrUPt";
    
    cout<<"\n\n\n\t\tEnter IP to connect to: ";
    gets(ip);
    
    sockaddr_in ser;
    sockaddr addr;
    
    
    ser.sin_family=AF_INET;
    ser.sin_port=htons(123);                    //Set the port
    ser.sin_addr.s_addr=inet_addr(ip);        //Set the address we want to connect to
    
    memcpy(&addr,&ser,sizeof(SOCKADDR_IN));
    
    res = WSAStartup(MAKEWORD(1,1),&data);        //Start Winsock
    cout<<"\n\nWSAStartup"
        <<"\nVersion: "<<data.wVersion
        <<"\nDescription: "<<data.szDescription
        <<"\nStatus: "<<data.szSystemStatus<<endl;

    if(res != 0)
        s_cl("WSAStarup failed",WSAGetLastError());

    sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);        //Create the socket
        if(sock==INVALID_SOCKET )
            s_cl("Invalid Socket ",WSAGetLastError());
        else if(sock==SOCKET_ERROR)
            s_cl("Socket Error)",WSAGetLastError());
        else
            cout<<"Socket Established"<<endl;
    

    
    res=connect(sock,&addr,sizeof(addr));                //Connect to the server
        if(res !=0 )
        {
            s_cl("SERVER UNAVAILABLE",res);
        }
        else
        {
            cout<<"\nConnected to Server: ";
            memcpy(&ser,&addr,sizeof(SOCKADDR));
        }
    
    char RecvdData[100] = "";
    int ret;

    while(true)
    {
        strcpy(buf,"");
        cout<<"\nEnter message to send ->\n";
        fgets(buf,sizeof(buf),stdin);
        
        
        Sleep(5); 
        res = send(sock,buf,sizeof(buf),0);    
         
         if(res==0)
         {    
            //0==other side terminated conn
            printf("\nSERVER terminated connection\n");
            Sleep(40);
            closesocket(client);
            client = 0;
            break;
         }
         else if(res==SOCKET_ERROR)
         {    
            //-1 == send error
            printf("Socket error\n");
            Sleep(40);
            s_handle(res);
            break;
         }
       
       ret = recv(sock,RecvdData,sizeof(RecvdData),0);
       if(ret > 0)
       { 
        cout<<endl<<RecvdData;
        strcpy(RecvdData,"");
       }
    }    
    
    closesocket(client);
    WSACleanup();
}