There are only four hundred lines of server code, mainly acceptthread and helperthread thread. The Code is as follows:
// Server. CPP: defines the entry point for the console application. <br/> // </P> <p> # include "stdafx. H "<br/> # include <iostream. h> <br/> # include <afx. h> <br/> # include <WINBASE. h> <br/> # include <winsock2.h> <br/> # include <process. h> <br/> # include <list> <br/> # include "client. H "</P> <p>/* <br/> * the first letter of the variable is lowercase, and the letter indicates the type of the variable, such as nerrcode. error code that is an integer <br/> * the first letter of the function is capitalized and indicates the function. For example, void acceptthread (void ). the thread that accepts the connection <br/> */<br/> # pragma comment (Lib, "ws2_32.lib") </P> <p> using namespace STD; <br/> typedef list <cclient *> clientlist; // linked list </P> <p> # define serverport5556 // server TCP port <br/> # define server_setup_fail1 // server startup failure </P> <p> # define timefor_thread_exit5000 // sleep time of the main thread <br/> # define timefor_thread_help1500 // The Exit Time of the cleanup resource thread <br/> # define timefor_thread_sleep500 // wait for the sleep time of the client request thread </P> <p> handlehthread Accept; // accept the client connection thread handle <br/> handlehthreadhelp; // release the resource thread handle <br/> socketsserver; // listener socket <br/> boolbserverrunning; // The server's working status <br/> handlehserverevent; // closes the server event object <br/> clientlistclientlist; // manages the connected linked list <br/> critical_sectioncsclientlist; // protect the critical area object of the linked list </P> <p> boolinitsever (void); // initialization <br/> boolstartservice (void ); // start the service <br/> voidstopservice (void); // stop the service <br/> boolcreatehelperandacceptthread (void); // create a connection thread for the receiving client <br/> V Oidexitserver (void); // server logout </P> <p> voidinitmember (void); // initialize the global variable <br/> boolinitsocket (void ); // initialize socket </P> <p> voidshowtipmsg (bool bfirstinput); // display the prompt message <br/> voidshowserverstartmsg (bool bsuc ); // display that the server has been started <br/> voidshowserverexitmsg (void); // display that the server is exiting </P> <p> DWORD _ stdcallhelperthread (void * pparam ); // release resources <br/> DWORD _ stdcall acceptthread (void * pparam); // accept the client connection thread <br/> voidshowconnectnum (); // display the number of client connections </ P> <p> int main (INT argc, char * argv []) <br/>{< br/> // initialize the server <br/> If (! Initsever () <br/>{< br/> exitserver (); <br/> return server_setup_fail; <br/>}</P> <p> // start the service <br/> If (! Startservice () <br/>{< br/> showserverstartmsg (false); <br/> exitserver (); <br/> return server_setup_fail; <br/>}</P> <p> // stop the service <br/> stopservice (); </P> <p> // server logout <br/> exitserver (); </P> <p> return 0; <br/>}</P> <p>/** <br/> * initialization <br/> */<br/> boolinitsever (void) <br/>{</P> <p> initmember (); // initialize the global variable </P> <p> // initialize the socket <br/> If (! Initsocket () <br/> return false; </P> <p> return true; <br/>}</P> <p>/** <br/> * initialize the global variable <br/> */<br/> voidinitmember (void) <br/>{< br/> initializecriticalsection (& csclientlist); // initialize the critical section <br/> hserverevent = createevent (null, true, false, null ); // manually set the event and initialize it to the State without an information number <br/> hthreadaccept = NULL; // set it to null <br/> hthreadhelp = NULL; // set to null <br/> sserver = invalid_socket; // set to invalid socket <br/> bserverrunning = false ;// The server is not running <br/> clientlist. clear (); // clear the linked list <br/>}</P> <p>/** <br/> * initialize socket <br/> */<br/> bool initsocket (void) <br/>{< br/> // return value <br/> int reval; </P> <p> // initialize Windows Sockets DLL <br/> wsadata wsdata; <br/> reval = wsastartup (makeword (2, 2), & wsdata); </P> <p> // create a socket <br/> sserver = socket (af_inet, sock_stream, 0); <br/> If (invalid_socket = sserver) <br/> return false; </P> <p> // set the socket non-blocking mode <br/> unsigned long Ul = 1; <br/> reval = ioctlsocket (sserver, fionbio, (unsigned long *) & UL); <br/> If (socket_error = reval) <br/> return false; </P> <p> // bind a socket <br/> sockaddr_in seraddr; <br/> seraddr. sin_family = af_inet; <br/> seraddr. sin_port = htons (SERVERPORT); <br/> seraddr. sin_addr.s_un.s_addr = inaddr_any; <br/> reval = BIND (sserver, (struct sockaddr *) & seraddr, sizeof (seraddr); <br/> If (socket_error = reval) <br/> Return false; </P> <p> // listener <br/> reval = listen (sserver, somaxconn); <br/> If (socket_error = reval) <br/> return false; </P> <p> return true; <br/>}</P> <p>/** <br/> * start the service <br/> */<br/> boolstartservice (void) <br/>{< br/> bool reval = true; // return value </P> <p> showtipmsg (true ); // prompt the user to enter </P> <p> char cinput; // enter the character <br/> DO <br/>{< br/> CIN> cinput; <br/> If ('s '= cinput |'s' = cinput) <br/>{< br/> If (createhelpera Ndacceptthread () // create a thread to clear resources and accept client requests <br/>{< br/> showserverstartmsg (true ); // information about successful thread creation <br/>}else {<br/> reval = false; <br/>}< br/> break; // jump out of the loop body </P> <p >}else {<br/> showtipmsg (true ); <br/>}</P> <p>} while (cinput! = 'S' & // The character 's' or 'S' must be entered. <br/> cinput! ='S '); </P> <p> return reval; <br/>}</P> <p>/** <br/> * stop the service <br/> */<br/> voidstopservice (void) <br/>{< br/> bool reval = true; // return value </P> <p> showtipmsg (false ); // prompt the user to enter </P> <p> char cinput; // The input operation character <br/> for (; bserverrunning ;) <br/>{< br/> CIN> cinput; <br/> If (cinput = 'E' | cinput = 'E ') <br/>{< br/> If (idok = MessageBox (null, "Are you sure? ", // Message box waiting for user confirmation to exit <br/>" server ", mb_okcancel) <br/>{< br/> break; // jump out of the loop body <br/>} else {<br/> sleep (timefor_thread_exit ); // thread sleep <br/>}< br/>} else {<br/> sleep (timefor_thread_exit ); // thread sleep <br/>}</P> <p> bserverrunning = false; // server logout </P> <p> showserverexitmsg (); // Display Server exit Information </P> <p> sleep (timefor_thread_exit); // give other threads time to exit </P> <p> waitforsingleobject (hserverevent, infinite ); // events waiting for the resource to be cleared </P> <p> return; <br/>} </P> <p>/** <br/> * display prompt information <br/> */<br/> voidshowtipmsg (bool bfirstinput) <br/>{< br/> If (bfirstinput) // The first time <br/>{< br/> cout <Endl; <br/> cout <Endl; <br/> cout <"**********************" <Endl; <br/> cout <"**" <Endl; <br/> cout <"* s (s): Start server *" <Endl; <br/> cout <"**" <Endl; <br/> cout <"**********************" <Endl; <br/> cout <"Please input:" <Endl; </P> <p >}else {// Exit the server <br/> cout <Endl; <br/> cout <"**********************" <Endl; <br/> cout <"**" <Endl; <br/> cout <"* E (e): Exit server *" <Endl; <br/> cout <"**" <Endl; <br/> cout <"**********************" <Endl; <br/> cout <"Please input:" <Endl; <br/>}< br/>/** <br/> * release resources <br/> */<br/> void exitserver (void) <br/>{< br/> deletecriticalsection (& csclientlist ); // Release the critical zone object <br/> closehandle (hserverevent); // release the event object handle <br/> closesocket (sserver ); // disable socket <br/> wsacleanup (); // uninstall Windows Sockets DLL <br/>}</P> <p>/** <br/> * create a resource release thread and a client request receiving thread <br/> * /<br/> bool createhelperandacceptthread (void) <br/>{</P> <p> bserverrunning = true; // set the server to running status </P> <p> // create a resource release thread <br/> unsigned long ulthreadid; <br/> hthreadhelp = createthread (null, 0, helperthread, null, 0, & ulthreadi D); <br/> If (null = hthreadhelp) <br/>{< br/> bserverrunning = false; <br/> return false; <br/>} else {<br/> closehandle (hthreadhelp ); <br/>}</P> <p> // create a receiving client request thread <br/> hthreadaccept = createthread (null, 0, acceptthread, null, 0, & ulthreadid); <br/> If (null = hthreadaccept) <br/>{< br/> bserverrunning = false; <br/> return false; <br/>} else {<br/> closehandle (hthreadaccept); <br/>}</P> <p> return true; <br />}</P> <p>/** <br/> * message indicating the server startup Success and Failure <br/> */<br/> void showserverstartmsg (bool bsuc) <br/>{< br/> If (bsuc) <br/> {<br/> cout <"************************" <Endl; <br/> cout <"**" <Endl; <br/> cout <"* server succeeded! * "<Endl; <br/> cout <" ** "<Endl; <br/> cout <"**********************" <Endl; <br/>} else {<br/> cout <"***********************" <endl; <br/> cout <"**" <Endl; <br/> cout <"* server failed! * "<Endl; <br/> cout <" ** "<Endl; <br/> cout <"**********************" <Endl; <br/>}</P> <p>/** <br/> * display the server logout message <br/> */<br /> void showserverexitmsg (void) <br/> {</P> <p> cout <"**********************" <<Endl; <br/> cout <"**" <Endl; <br/> cout <"* server exit... * "<Endl; <br/> cout <" ** "<Endl; <br/> cout <"**********************" <Endl; <br/>}</P> <p>/** <br/> * Connect to the client <br/> */<br/> DWORD _ stdcall acceptthread (void * pparam) <br/>{< br/> socket saccept; // accept the Socket connected by the client <br/> sockaddr_in addrclient; // The socket address of the client </P> <p> for (; bserverrunning ;) // server status <br/>{< br/> memset (& addrclient, 0, sizeof (sockaddr_in )); // initialization <br/> intlenclient = sizeof (sockaddr_in); // address length <br/> saccept = accept (sserver, (sockaddr *) & addrclient, & lenclient ); // accept customer requests </P> <p> If (invalid_socket = SACC EPT) <br/>{< br/> int nerrcode = wsagetlasterror (); <br/> If (nerrcode = wsaewouldblock) // an unblocking socket operation cannot be completed immediately <br/>{< br/> sleep (timefor_thread_sleep); <br/> continue; // continue waiting <br/>} else {<br/> return 0; // exit by thread <br/>}</P> <p >}< br/> else // receives client requests <br/>{< br/> cclient * pclient = new cclient (saccept, addrclient); // create a client object <br/> entercriticalsection (& csclientlist); // enter the clientlist in the critical section <br/>. push_back (pclient); // Add Linked List <br/> leavecriticalsection (& csclientlist); // exit the critical section </P> <p> pclient-> startruning (); // set up a receiving data and sending data thread for the accepted client <br/>}</P> <p> return 0; // exit the thread <br/>}</P> <p>/** <br/> * clear resources <br/> */<br/> DWORD _ stdcall helperthread (void * pparam) <br/>{< br/> for (; bserverrunning;) // the server is running <br/>{< br/> entercriticalsection (& csclientlist ); // enter the critical section </P> <p> // clear the memory space of the disconnected client. <br/> clientlist: iterator iter = clientlist. begi N (); <br/> for (ITER; iter! = Clientlist. end ();) <br/>{< br/> cclient * pclient = (cclient *) * ITER; <br/> If (pclient-> isexit ()) // The client thread has exited <br/>{< br/> clientlist. erase (ITER ++); // delete a node <br/> Delete pclient; // release the memory <br/> pclient = NULL; <br/>} else {<br/> ITER ++; // move the pointer down <br/>}</P> <p> leavecriticalsection (& csclientlist ); // leave the critical section </P> <p> sleep (timefor_thread_help); <br/>}</P> <p> // The server stops working <br/> If (! Bserverrunning) <br/>{< br/> // disconnect each connection and the thread exits <br/> entercriticalsection (& csclientlist); <br/> clientlist :: iterator iter = clientlist. begin (); <br/> for (ITER; iter! = Clientlist. end ();) <br/>{< br/> cclient * pclient = (cclient *) * ITER; <br/> // if the client connection still exists, disconnect and the thread exits. <br/> If (pclient-> isconning () <br/>{< br/> pclient-> disconning (); <br/>}< br/> + ITER; <br/>}< br/> // exit the critical section <br/> leavecriticalsection (& csclientlist ); </P> <p> // specify the thread time for the client to automatically exit. <br/> sleep (timefor_thread_sleep ); </P> <p> // enter the critical section <br/> entercriticalsection (& csclientlist ); </P> <p> // make sure that the memory space allocated to each client is recycled. <Br/> // if you do not add the while loop, this may happen. When pclient-> isexit (), the thread has not exited. <Br/> // you need to re-judge from the beginning of the linked list. <Br/> while (0! = Clientlist. Size () <br/>{< br/> iter = clientlist. Begin (); <br/> for (ITER; iter! = Clientlist. end ();) <br/>{< br/> cclient * pclient = (cclient *) * ITER; <br/> If (pclient-> isexit ()) // The client thread has exited <br/>{< br/> clientlist. erase (ITER ++); // delete a node <br/> Delete pclient; // release memory space <br/> pclient = NULL; <br/>} else {<br/> ITER ++; // move the pointer down <br/>}< br/> // set the thread time for the client to automatically exit <br/> sleep (timefor_thread_sleep ); <br/>}< br/> leavecriticalsection (& csclientlist); // exit the critical section </P> <p >}</P> <p> clientlist. clear (); // clear the linked list </P> <p> setevent (hserverevent); // notify the main thread to exit </P> <p> return 0; <br/>}