C++ネットワークプログラミング学習:ソースコードのパッケージ


ネットワークプログラミング学習レコード
  • 使用言語はC/C+
  • ソースコードサポートプラットフォームは、Windows/Linux
  • 笔记一:基础TCP服务端/クライアント 点我跳转笔记二:ネットワークデータメッセージの送受信 点我跳转笔记三:selectネットワークモデル 点我跳转笔记四:プラットフォームをまたいでWindowsをサポート、Linuxシステム 点我跳转笔记5:ソースコードのパッケージ 点我跳转笔记6:バッファオーバーフローと粘着包分包 点我跳转笔记7:サービス端マルチスレッド分离业务処理高负荷 点我跳转笔记
    ノート5
  • ネットワークプログラミング学習記録
  • 一、なぜパッケージ操作を行うのか
  • 二、パッケージの考え方と関連
  • 1.パッケージヘッダファイル選択
  • 2.クライアントクラスのパッケージ
  • 3.サービス側クラスのパッケージ
  • 三、パッケージ後の詳細なソースコードとその注釈
  • 1.クライアント
  • TcpClient.hpp
  • client_test.cpp

  • 2.サービス側
  • TcpServer.hpp
  • server_test.cpp



  • 一、なぜパッケージ操作を行うのか
    オブジェクト向けプログラミング言語として,オブジェクト向けの考え方でソースコードの作成を行う.  主なソースコードをカプセル化した後、クライアントとサービス側のコードの作成がより明確になり、論理性がより強く、開発とメンテナンスが容易になった.また,今後のサービス側高同時テストでは,複数の接続を新規作成してテストするのが容易である. 本ノートでは、ノート4のソースコードに基づいてパッケージ化し、クライアントとサービス側のソースコードをパッケージ化する際の考え方と手順を記録します.最終ソースコードはクライアントパッケージクラスファイルTcpClientである.hppとサービス側はクラスファイルTcpServerをカプセル化する.hpp、およびクライアントソースclient_test.cppとサービス側ソースサーバ_test.cpp.
    二、パッケージの考え方と関連
    1.カプセル化されたヘッダファイルの選択
    カプセル化クラスは、まずヘッダファイルにカプセル化性を体現しなければならない.今回のパッケージでは、より便利に保存できるようにhppヘッダファイルを選びました.すなわち、クラス宣言とクラス定義はこのファイルにあります.
    2.クライアントクラスのカプセル化
    まず、クライアントの大まかな流れは以下の通りです.
    1.  socket
    2.     
    3.            
    while(true)
    {
         
    	4.  select                
    	5.(  /  )
    }
    6.  socket
    
       :
    while(1)
    {
         
    	1.    
    	2.    
    }
    

    したがって、パッケージ化する方法は次のとおりです.
    	//   socket
    	int InitSocket();
    	//      
    	int Connect(const char *ip,unsigned short port);
    	//  socket
    	void CloseSocket();
    	//           
    	bool OnRun();
    	//        
    	bool IsRun();
    	//     
    	int SendData(DataHeader *_head);
    	//    
    	int RecvData(SOCKET _temp_socket);
    	//    
    	virtual void NetMsg(DataHeader *_head);
    

      この考え方に従って、クライアントのソースコードの考え方は:
    1.InitSocket();//  socket
    2.Connect(const char *ip,unsigned short port);//        IP   
    3.            
    while(4.IsRun())//       
    {
         
    	5.OnRun();//          
    }
    6.CloseSocket();//  socketwhile(1.IsRun())//       
    {
         
    	2.    
    	3.SendData(DataHeader *_head);
    }
    

      OnRun()メソッドではselectネットワーク構造を使用しており、selectが処理対象イベントをフィルタリングした後、RecvData()メソッドを使用してパケットとパケットの受信を行い、その後NetMsg()メソッドを呼び出し、パケットヘッダのメッセージタイプに応じてパケットデータを処理する.NetMsg()メソッドはダミーメソッドであり,後でこのパッケージクラスを呼び出すと継承リロード操作を行うことができ,データ応答の操作を変更しやすい.
  • 関連ソースコードは以下の通りである:
  • 	//           
    	bool OnRun()
    	{
         
    		if(IsRun())//           
    		{
         
    			fd_set _fdRead;//     
    			FD_ZERO(&_fdRead);//      
    			FD_SET(_sock,&_fdRead);//     
    			timeval _t = {
         1,0};//select       
    			//  seclect 
    			int _ret = select(_sock+1,&_fdRead,NULL,NULL,&_t);
    			if(_ret<0)
    			{
         
    				printf("seclect    
    "
    ); return false; } if(FD_ISSET(_sock,&_fdRead))// socket { FD_CLR(_sock,&_fdRead);// if(-1 == RecvData(_sock)) { CloseSocket(); return false; } } return true; } return false; } // int RecvData(SOCKET _temp_socket)// { // char buffer[4096] = { }; // int _buf_len = recv(_temp_socket,buffer,sizeof(DataHeader),0); DataHeader *_head = (DataHeader*)buffer; if(_buf_len<=0) { printf(" ,
    "
    ); return -1; } recv(_temp_socket,buffer+sizeof(DataHeader),_head->date_length-sizeof(DataHeader),0); // NetMsg(_head); return 0; } // virtual void NetMsg(DataHeader *_head) { printf(" , :%d, :%d
    "
    ,_head->cmd,_head->date_length); switch(_head->cmd) { case CMD_LOGINRESULT:// { LoginResult *_result = (LoginResult*)_head; printf(" :%d
    "
    ,_result->Result); } break; case CMD_LOGOUTRESULT:// { LogoutResult *_result = (LogoutResult*)_head; printf(" :%d
    "
    ,_result->Result); } break; case CMD_NEW_USER_JOIN:// { NewUserJoin *_result = (NewUserJoin*)_head; printf(" :%s
    "
    ,_result->UserName); } } }

    また、カプセル化されているため、メソッドを呼び出す際にステップエラーが発生する可能性があります.たとえば、新しいソケットを作成しないでconnect接続を行うか、ソケットを閉じるか、データの転送にエラーがあるなど、問題が発生します.私がこのような問題を解決する方法は、多くの判定を加えることです.例えば、ソケットが確立されているか、あるいは入力データに誤りがあるかなどを判定し、その後、状況に応じて処理する.詳細は下記をご覧ください.
    3.サービス側クラスのパッケージ
    まず、クライアントの大まかな流れは以下の通りです.
    1.  socket
    2.    IP
    3.    
    while(true)
    {
         
    	4.  select            socket
    	5.                
    	6.(     )
    }
    7.  socket
    

    したがって、パッケージ化する方法は次のとおりです.
    	//   socket 
    	int InitSocket();
    	//  IP/  
    	int Bind(const char* ip,unsigned short port);
    	//    
    	int Listen(int n);
    	//    
    	int Accept();
    	//  socket 
    	void CloseSocket();
    	//           
    	bool OnRun();
    	//        
    	bool IsRun();
    	//     
    	int SendData(DataHeader *_head,SOCKET _temp_socket);
    	//    
    	int RecvData(SOCKET _temp_socket);
    	//    
    	void NetMsg(DataHeader *_head,SOCKET _temp_socket);
    

      この考え方に従って、クライアントのソースコードの考え方は:
    1.InitSocket();//  socket
    2.Bind(const char* ip,unsigned short port);//    IP
    3.Listen(int n);//    
    while(4.IsRun())//     
    {
         
    	5.OnRun();//          
    }
    6.CloseSocket();//  socket
    

    OnRun()メソッドではselectネットワーク構造が使用されます.selectが処理対象イベントをフィルタリングした後、新しい接続の場合、Accept()メソッドを使用して新しいクライアント接続操作を行います.クライアントに接続されている受信対象イベントの場合は、RecvData()メソッドを使用してパケットヘッダとパケットの受信を行い、その後NetMsg()メソッドを呼び出し、パケットヘッダのメッセージタイプに応じてパケットデータを処理します.NetMsg()メソッドはダミーメソッドであり,後でこのパッケージクラスを呼び出すと継承リロード操作を行うことができ,データ応答の操作を変更しやすい.
  • 関連ソースコードは以下の通りである:
  • 	//           
    	bool OnRun()
    	{
         
    		if(IsRun())
    		{
         
    			fd_set _fdRead;//     
    			fd_set _fdWrite;
    			fd_set _fdExcept;
    			FD_ZERO(&_fdRead);//     
    			FD_ZERO(&_fdWrite); 
    			FD_ZERO(&_fdExcept); 
    			FD_SET(_sock,&_fdRead);//     
    			FD_SET(_sock,&_fdWrite); 
    			FD_SET(_sock,&_fdExcept);
    			timeval _t = {
         2,0};//select       
    			SOCKET _maxSock = _sock;//  socket 
    			//          read   
    			for(int n=_clients.size()-1; n>=0; --n)
    			{
         
    				FD_SET(_clients[n],&_fdRead);
    				if(_maxSock < _clients[n])
    				{
         
    					_maxSock = _clients[n];
    				}
    			}
    			//select    select 
    			int _ret = select(_maxSock+1,&_fdRead,&_fdWrite,&_fdExcept,&_t); 
    			if(_ret<0)
    			{
         
    				printf("select    
    "
    ); CloseSocket(); return false; } if(FD_ISSET(_sock,&_fdRead))// socket { FD_CLR(_sock,&_fdRead);// Accept();// } // socket for(int n=0; n<_clients.size(); ++n) { if(FD_ISSET(_clients[n],&_fdRead)) { if(-1 == RecvData(_clients[n]))// { std::vector<SOCKET>::iterator iter = _clients.begin()+n;// if(iter != _clients.end())// { _clients.erase(iter);// } } } } //printf("
    ");
    return true; } return false; } // int RecvData(SOCKET _temp_socket)// { // char buffer[4096] = { }; // int _buf_len = recv(_temp_socket,buffer,sizeof(DataHeader),0); DataHeader *_head = (DataHeader*)buffer; if(_buf_len<=0) { printf("
    "
    ); return -1; } recv(_temp_socket,buffer+sizeof(DataHeader),_head->date_length-sizeof(DataHeader),0); // NetMsg(_head,_temp_socket); return 0; } // void NetMsg(DataHeader *_head,SOCKET _temp_socket) { printf(" , :%d, :%d
    "
    ,_head->cmd,_head->date_length); switch(_head->cmd) { case CMD_LOGIN:// { Login *_login = (Login*)_head; /* */ printf("%s
    :%s
    "
    ,_login->UserName,_login->PassWord); LoginResult *_result = new LoginResult; _result->Result = 1; SendData(_result,_temp_socket); } break; case CMD_LOGOUT:// { Logout *_logout = (Logout*)_head; /* */ printf("%s
    "
    ,_logout->UserName); LogoutResult *_result = new LogoutResult(); _result->Result = 1; SendData(_result,_temp_socket); } break; default:// { _head->cmd = CMD_ERROR; _head->date_length = 0; SendData(_head,_temp_socket); } break; } }

    また、カプセル化されているため、メソッドを呼び出す際にステップエラーが発生する可能性があります.たとえば、新しいソケットを作成しないままbindバインドポートIPを実行したり、ソケットをオフにしたり、データの転送に誤りがあったりすると、問題が発生します.私がこのような問題を解決する方法は、多くの判定を加えることです.例えば、ソケットが確立されているか、あるいは入力データに誤りがあるかなどを判定し、その後、状況に応じて処理する.詳細は下記をご覧ください.
    三、パッケージ後の詳細なソースコードとその注釈
    1.クライアント
    TcpClient.hpp
    #ifndef _TcpClient_hpp_
    #define _TcpClient_hpp_
    
    #ifdef _WIN32
    	#define WIN32_LEAN_AND_MEAN
    	#include
    	#include
    	#pragma comment(lib,"ws2_32.lib") 
    #else
    	#include
    	#include
    	#include
    	
    	#define SOCKET int
    	#define INVALID_SOCKET (SOCKET)(~0)
    	#define SOCKET_ERROR (-1)
    #endif
    //         
    enum cmd 
    {
         
    	CMD_LOGIN,//   
    	CMD_LOGINRESULT,//     
    	CMD_LOGOUT,//   
    	CMD_LOGOUTRESULT,//     
    	CMD_NEW_USER_JOIN,//      
    	CMD_ERROR//   
    };
    //       
    struct DataHeader 
    {
         
    	short cmd;//  
    	short date_length;//     	
    };
    // 1           
    struct Login : public DataHeader 
    {
         
    	Login()//      
    	{
         
    		this->cmd = CMD_LOGIN;
    		this->date_length = sizeof(Login); 
    	}
    	char UserName[32];//    
    	char PassWord[32];//   
    };
    // 2          
    struct LoginResult : public DataHeader 
    {
         
    	LoginResult()//      
    	{
         
    		this->cmd = CMD_LOGINRESULT;
    		this->date_length = sizeof(LoginResult); 
    	}
    	int Result;
    };
    // 3          
    struct Logout : public DataHeader 
    {
         
    	Logout()//      
    	{
         
    		this->cmd = CMD_LOGOUT;
    		this->date_length = sizeof(Logout); 
    	}
    	char UserName[32];//    
    };
    // 4          
    struct LogoutResult : public DataHeader 
    {
         
    	LogoutResult()//      
    	{
         
    		this->cmd = CMD_LOGOUTRESULT;
    		this->date_length = sizeof(LogoutResult); 
    	}
    	int Result;
    };
    // 5            
    struct NewUserJoin : public DataHeader 
    {
         
    	NewUserJoin()//      
    	{
         
    		this->cmd = CMD_NEW_USER_JOIN;
    		this->date_length = sizeof(NewUserJoin); 
    	}
    	char UserName[32];//    
    };
    
    #include
    
    class TcpClient
    {
         
    public:
    	//   
    	TcpClient()
    	{
         
    		_sock = INVALID_SOCKET; 
    	}
    	
    	//   
    	virtual ~TcpClient()
    	{
         
    		//  socket 
    		CloseSocket();
    	}
    	
    	//   socket   1    
    	int InitSocket()
    	{
         
    #ifdef _WIN32
    		//  windows socket 2,x   
    		WORD ver = MAKEWORD(2,2); 
    		WSADATA dat;
    		if(0 != WSAStartup(ver,&dat))
    		{
         
    			return -1;//-1      
    		}
    #endif 
    		//  socket 
    		if(INVALID_SOCKET != _sock)
    		{
         
    			printf("    
    "
    ,_sock); CloseSocket();// } _sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if(INVALID_SOCKET == _sock) { return 0;//0 socket } return 1; } // 1 int Connect(const char *ip,unsigned short port) { // if(INVALID_SOCKET == _sock) { InitSocket(); } // sockaddr_in _sin = { }; _sin.sin_family = AF_INET;//IPV4 _sin.sin_port = htons(port);// #ifdef _WIN32 _sin.sin_addr.S_un.S_addr = inet_addr(ip);//IP #else _sin.sin_addr.s_addr = inet_addr(ip);//IP #endif if(SOCKET_ERROR == connect(_sock,(sockaddr*)&_sin,sizeof(sockaddr_in))) { return 0;// } else { return 1;// } } // socket void CloseSocket() { if(INVALID_SOCKET != _sock) { #ifdef _WIN32 // socket closesocket(_sock); // windows socket WSACleanup(); #else // socket/LINUX close(_sock); #endif _sock = INVALID_SOCKET; } } // bool OnRun() { if(IsRun())// { fd_set _fdRead;// FD_ZERO(&_fdRead);// FD_SET(_sock,&_fdRead);// timeval _t = { 1,0};//select // seclect int _ret = select(_sock+1,&_fdRead,NULL,NULL,&_t); if(_ret<0) { printf("seclect
    "
    ); return false; } if(FD_ISSET(_sock,&_fdRead))// socket { FD_CLR(_sock,&_fdRead);// if(-1 == RecvData(_sock)) { CloseSocket(); return false; } } return true; } return false; } // bool IsRun() { return _sock != INVALID_SOCKET; } // int SendData(DataHeader *_head) { if(IsRun() && _head) { send(_sock,(const char*)_head,_head->date_length,0); return 1; } return 0; } // int RecvData(SOCKET _temp_socket)// { // char buffer[4096] = { }; // int _buf_len = recv(_temp_socket,buffer,sizeof(DataHeader),0); DataHeader *_head = (DataHeader*)buffer; if(_buf_len<=0) { printf(" ,
    "
    ); return -1; } recv(_temp_socket,buffer+sizeof(DataHeader),_head->date_length-sizeof(DataHeader),0); // NetMsg(_head); return 0; } // virtual void NetMsg(DataHeader *_head) { printf(" , :%d, :%d
    "
    ,_head->cmd,_head->date_length); switch(_head->cmd) { case CMD_LOGINRESULT:// { LoginResult *_result = (LoginResult*)_head; printf(" :%d
    "
    ,_result->Result); } break; case CMD_LOGOUTRESULT:// { LogoutResult *_result = (LogoutResult*)_head; printf(" :%d
    "
    ,_result->Result); } break; case CMD_NEW_USER_JOIN:// { NewUserJoin *_result = (NewUserJoin*)_head; printf(" :%s
    "
    ,_result->UserName); } } } private: SOCKET _sock; }; #endif

    client_test.cpp
    #include"TcpClient.hpp"
    #include
    
    void _cmdThread(TcpClient* tcp)//     
    {
         
    	while(tcp->IsRun())
    	{
         
    		//     
    		char _msg[256] = {
         };
    		scanf("%s",_msg);
    		//     
    		if(0 == strcmp(_msg,"exit"))
    		{
         
    			tcp->CloseSocket();
    			printf("    
    "
    ); break; } else if(0 == strcmp(_msg,"login")) { // Login _login; strcpy(_login.UserName,"hbxxy"); strcpy(_login.PassWord,"123456"); tcp->SendData(&_login); } else if(0 == strcmp(_msg,"logout")) { // Logout _logout; strcpy(_logout.UserName,"hbxxy"); tcp->SendData(&_logout); } else { printf("
    "
    ); } } } int main() { printf("Welcome
    "
    ); // tcp TcpClient *tcp1 = new TcpClient(); // socket tcp1->InitSocket(); // tcp1->Connect("127.0.0.1",8888); // UI std::thread t1(_cmdThread,tcp1); t1.detach();// // while(tcp1->IsRun()) { tcp1->OnRun(); } // tcp1->CloseSocket(); return 0; }

    2.サービス側
    TcpServer.hpp
    #ifndef _TcpServer_hpp_
    #define _TcpServer_hpp_
    
    #ifdef _WIN32
    	#define WIN32_LEAN_AND_MEAN
    	#include
    	#include
    	#pragma comment(lib,"ws2_32.lib")//         windows   
    #else
    	#include//selcet
    	#include//uni std
    	#include
    	
    	#define SOCKET int
    	#define INVALID_SOCKET (SOCKET)(~0)
    	#define SOCKET_ERROR (-1)
    #endif
    //         
    enum cmd 
    {
         
    	CMD_LOGIN,//   
    	CMD_LOGINRESULT,//     
    	CMD_LOGOUT,//   
    	CMD_LOGOUTRESULT,//     
    	CMD_NEW_USER_JOIN,//      
    	CMD_ERROR//   
    };
    //       
    struct DataHeader 
    {
         
    	short cmd;//  
    	short date_length;//     	
    };
    // 1           
    struct Login : public DataHeader 
    {
         
    	Login()//      
    	{
         
    		this->cmd = CMD_LOGIN;
    		this->date_length = sizeof(Login); 
    	}
    	char UserName[32];//    
    	char PassWord[32];//   
    };
    // 2          
    struct LoginResult : public DataHeader 
    {
         
    	LoginResult()//      
    	{
         
    		this->cmd = CMD_LOGINRESULT;
    		this->date_length = sizeof(LoginResult); 
    	}
    	int Result;
    };
    // 3          
    struct Logout : public DataHeader 
    {
         
    	Logout()//      
    	{
         
    		this->cmd = CMD_LOGOUT;
    		this->date_length = sizeof(Logout); 
    	}
    	char UserName[32];//    
    };
    // 4          
    struct LogoutResult : public DataHeader 
    {
         
    	LogoutResult()//      
    	{
         
    		this->cmd = CMD_LOGOUTRESULT;
    		this->date_length = sizeof(LogoutResult); 
    	}
    	int Result;
    };
    // 5            
    struct NewUserJoin : public DataHeader 
    {
         
    	NewUserJoin()//      
    	{
         
    		this->cmd = CMD_NEW_USER_JOIN;
    		this->date_length = sizeof(NewUserJoin); 
    	}
    	char UserName[32];//    
    };
    
    #include
    
    class TcpServer
    {
         
    public:
    	//   
    	TcpServer()
    	{
         
    		_sock = INVALID_SOCKET; 
    	}
    	
    	//   
    	virtual ~TcpServer()
    	{
         
    		//  socket 
    		CloseSocket();
    	}
    	
    	//   socket   1    
    	int InitSocket()
    	{
         
    #ifdef _WIN32
    		//  windows socket 2,x   
    		WORD ver = MAKEWORD(2,2); 
    		WSADATA dat;
    		if(0 != WSAStartup(ver,&dat))
    		{
         
    			return -1;//-1      
    		}
    #endif 
    		//  socket 
    		if(INVALID_SOCKET != _sock)
    		{
         
    			printf("    
    "
    ,_sock); CloseSocket();// } _sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if(INVALID_SOCKET == _sock) { return 0;//0 socket } return 1; } // IP/ int Bind(const char* ip,unsigned short port) { // if(INVALID_SOCKET == _sock) { InitSocket(); } // IP sockaddr_in _myaddr = { }; _myaddr.sin_family = AF_INET;//IPV4 _myaddr.sin_port = htons(port);// #ifdef _WIN32 if(ip)//ip { _myaddr.sin_addr.S_un.S_addr = inet_addr(ip);//IP } else { _myaddr.sin_addr.S_un.S_addr = INADDR_ANY;//IP } #else if(ip)//ip { _myaddr.sin_addr.s_addr = inet_addr(ip);//IP } else { _myaddr.sin_addr.s_addr = INADDR_ANY;//IP } #endif if(SOCKET_ERROR == bind(_sock,(sockaddr*)&_myaddr,sizeof(sockaddr_in)))//socket ( )sockaddr { printf("
    "
    ); return 0; } else { printf("
    %d
    "
    ,port); return 1; } } // int Listen(int n) { // if(INVALID_SOCKET == _sock) { printf(" IP
    "
    ); return 0; } // if(SOCKET_ERROR == listen(_sock,n))// { printf("
    "
    ); return 0; } else { printf("
    "
    ); return 1; } } // int Accept() { // sockaddr_in _clientAddr = { };// sockadd int _addr_len = sizeof(sockaddr_in);// sockadd SOCKET _temp_socket = INVALID_SOCKET;// #ifdef _WIN32 _temp_socket = accept(_sock,(sockaddr*)&_clientAddr,&_addr_len);// #else _temp_socket = accept(_sock,(sockaddr*)&_clientAddr,(socklen_t*)&_addr_len);// #endif if(INVALID_SOCKET == _temp_socket)// { printf(" , SOCKET
    "
    ,_temp_socket); return 0; } else { printf("
    IP :%s
    "
    , inet_ntoa(_clientAddr.sin_addr)); // NewUserJoin _user_join; strcpy(_user_join.UserName,inet_ntoa(_clientAddr.sin_addr)); for(int n=0;n<_clients.size();++n) { send(_clients[n],(const char*)&_user_join,sizeof(NewUserJoin),0); } // _clients.push_back(_temp_socket); return 1; } } // socket void CloseSocket() { if(INVALID_SOCKET != _sock) { #ifdef _WIN32 // socket for(int n=0; n<_clients.size(); ++n) { closesocket(_clients[n]); } // socket closesocket(_sock); // windows socket WSACleanup(); #else // socket for(int n=0; n<_clients.size(); ++n) { close(_clients[n]); } // socket/LINUX close(_sock); #endif _sock = INVALID_SOCKET; } } // bool OnRun() { if(IsRun()) { fd_set _fdRead;// fd_set _fdWrite; fd_set _fdExcept; FD_ZERO(&_fdRead);// FD_ZERO(&_fdWrite); FD_ZERO(&_fdExcept); FD_SET(_sock,&_fdRead);// FD_SET(_sock,&_fdWrite); FD_SET(_sock,&_fdExcept); timeval _t = { 2,0};//select SOCKET _maxSock = _sock;// socket // read for(int n=_clients.size()-1; n>=0; --n) { FD_SET(_clients[n],&_fdRead); if(_maxSock < _clients[n]) { _maxSock = _clients[n]; } } //select select int _ret = select(_maxSock+1,&_fdRead,&_fdWrite,&_fdExcept,&_t); if(_ret<0) { printf("select
    "
    ); CloseSocket(); return false; } if(FD_ISSET(_sock,&_fdRead))// socket { FD_CLR(_sock,&_fdRead);// Accept();// } // socket for(int n=0; n<_clients.size(); ++n) { if(FD_ISSET(_clients[n],&_fdRead)) { if(-1 == RecvData(_clients[n]))// { std::vector<SOCKET>::iterator iter = _clients.begin()+n;// if(iter != _clients.end())// { _clients.erase(iter);// } } } } //printf("
    ");
    return true; } return false; } // bool IsRun() { return _sock != INVALID_SOCKET; } // int SendData(DataHeader *_head,SOCKET _temp_socket) { if(IsRun() && _head) { send(_temp_socket,(const char*)_head,_head->date_length,0); return 1; } return 0; } // int RecvData(SOCKET _temp_socket)// { // char buffer[4096] = { }; // int _buf_len = recv(_temp_socket,buffer,sizeof(DataHeader),0); DataHeader *_head = (DataHeader*)buffer; if(_buf_len<=0) { printf("
    "
    ); return -1; } recv(_temp_socket,buffer+sizeof(DataHeader),_head->date_length-sizeof(DataHeader),0); // NetMsg(_head,_temp_socket); return 0; } // void NetMsg(DataHeader *_head,SOCKET _temp_socket) { printf(" , :%d, :%d
    "
    ,_head->cmd,_head->date_length); switch(_head->cmd) { case CMD_LOGIN:// { Login *_login = (Login*)_head; /* */ printf("%s
    :%s
    "
    ,_login->UserName,_login->PassWord); LoginResult *_result = new LoginResult; _result->Result = 1; SendData(_result,_temp_socket); } break; case CMD_LOGOUT:// { Logout *_logout = (Logout*)_head; /* */ printf("%s
    "
    ,_logout->UserName); LogoutResult *_result = new LogoutResult(); _result->Result = 1; SendData(_result,_temp_socket); } break; default:// { _head->cmd = CMD_ERROR; _head->date_length = 0; SendData(_head,_temp_socket); } break; } } private: SOCKET _sock; std::vector<SOCKET> _clients;// socket }; #endif

    server_test.cpp
    #include"TcpServer.hpp"
     
    int main() 
    {
         
    	printf("Welcome
    "
    ); // tcp TcpServer *tcp1 = new TcpServer(); // socket tcp1->InitSocket(); // IP tcp1->Bind(NULL,8888); // tcp1->Listen(5); // while(tcp1->IsRun()) { tcp1->OnRun(); } // tcp1->CloseSocket(); printf(" , "); getchar(); return 0; }