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(); }
Results 1 to 1 of 1
- 01 Jul. 2010 04:43pm #1
[C++]Client/Server Programming using threads.