首先,我们可以用到这个开源的开发包:
mdk(Micro-Development-Kit)微量级软件开发包,提供几个常用类,主要实现了一个高性能的并发服务器引擎
使用c++开发,是一个跨平台的开发包,支持linux32/linux64/win32/win64的类库 。
mdk服务器引擎,提出面向业务的服务器开发模式,根据服务器业务层最关心的3件事,抽象出连接发生(OnConnect),消息到达(OnClose),连接关闭(OnClose)3个接口,让服务器端开发者可以全身心的投入业务逻辑的开发中。
特点: 提供分布式支持,自身是一个server-client的结合体(即做服务器使用的同时,也可以像client一样去连接别的服务器,组成分布式系统),并且io接口统一到onconnect onmsg onclose中,不必区别对待 事件轮巡使用的是原生epoll iocp实现,确保了对io响应速度的完全掌控 几乎等同于lock free的并发算法,保证并发效率 欢迎大家共同学习使用。
或者是这里:
我们写客户端的时候可以用到里面 的socket类
socket.h如下:
// Socket.h: interface for the Socket class./////***********************************************************************************************************************************************/#ifndef MDK_SOCKET_H#define MDK_SOCKET_H#includeusing namespace std;#ifdef WIN32#include #define socklen_t int#else#include #include #include #include #include #include #include #include #include #include #define INVALID_SOCKET -1#define SOCKET_ERROR -1#define closesocket closetypedef int SOCKET;#endif#include #include #include namespace mdk{class Socket{public: enum SocketError { seTimeOut = -2, seSocketClose = -1, seError = -3, }; enum protocol { tcp = SOCK_STREAM, udp = SOCK_DGRAM, }; Socket(); Socket( SOCKET hSocket, protocol nProtocolType ); virtual ~Socket(); public: // SOCKET GetSocket(); /* */ bool Init(protocol nProtocolType); /** */ void Close(); // bool IsClosed(); // /* TCP */ int Send( const void* lpBuf, int nBufLen, int nFlags = 0 ); /* */ int Receive( void* lpBuf, int nBufLen, bool bCheckDataLength = false, long lSecond = 0, long lMinSecond = 0 ); // /*UDP */ int SendTo( const char *strIP, int nPort, const void* lpBuf, int nBufLen, int nFlags = 0 ); /* */ int ReceiveFrom( char* lpBuf, int nBufLen, std::string &strFromIP, int &nFromPort, bool bCheckDataLength = false, long lSecond = 0, long lMinSecond = 0 ); /* */ bool Connect( const char* lpszHostAddress, unsigned short nHostPort ); /* */ bool StartServer( int nPort ); /* */ bool Accept(Socket& rConnectedSocket); // void GetWanAddress( std::string& strWanIP, int& nWanPort ); // void GetLocalAddress( std::string& strWanIP, int& nWanPort ); /* */ bool SetSockMode( bool bWait = false ); /* */ bool SetSockOpt( int nOptionName, const void* lpOptionValue, int nOptionLen, int nLevel = SOL_SOCKET ); /* */ static bool SocketInit(void *lpVoid = NULL); static void SocketDestory(); // void GetLastErrorMsg( std::string &strError ); // // static bool InitForIOCP( SOCKET hSocket ); /* */ void Attach( SOCKET hSocket ); /* */ SOCKET Detach(); // // bool InitWanAddress(); // // bool InitLocalAddress(); protected: /* */ bool TimeOut( long lSecond, long lMinSecond ); // bool WaitData(); /* */ void GetAddress( const sockaddr_in &sockAddr, std::string &strIP, int &nPort ); /* */ bool Bind( unsigned short nPort, char *strIP = NULL ); /* */ bool Listen( int nConnectionBacklog = SOMAXCONN ); public:private: SOCKET m_hSocket;// bool m_bBlock;// bool m_bOpened;// sockaddr_in m_sockAddr; std::string m_strWanIP; int m_nWanPort; std::string m_strLocalIP; int m_nLocalPort;};}//namespace mdk#endif // MDK_SOCKET_H
socket.cpp的实现:
// Socket.cpp: implementation of the Socket class.////#include#include #include "Socket.h"#ifdef WIN32//#include #pragma comment ( lib, "ws2_32.lib" )#endifusing namespace std;namespace mdk{Socket::Socket(){ m_hSocket = INVALID_SOCKET; m_bBlock = true; m_bOpened = false;//}Socket::Socket( SOCKET hSocket, protocol nProtocolType ){ m_hSocket = hSocket; m_bBlock = true; m_bOpened = false;// Init(nProtocolType); InitWanAddress(); InitLocalAddress();}Socket::~Socket(){}/**/bool Socket::SocketInit(void *lpVoid){#ifdef WIN32 // initialize Winsock library WSADATA *lpwsaData = (WSADATA *)lpVoid; WSADATA wsaData; if (lpwsaData == NULL) lpwsaData = &wsaData; WORD wVersionRequested = MAKEWORD(1, 1); __int32 nResult = WSAStartup(wVersionRequested, lpwsaData); if (nResult != 0) return false; if (LOBYTE(lpwsaData->wVersion) != 1 || HIBYTE(lpwsaData->wVersion) != 1) { WSACleanup(); return false; }#endif return true;}void Socket::SocketDestory(){#ifdef WIN32 WSACleanup();#endif}void Socket::GetLastErrorMsg( string &strError ){ char strErr[1024];#ifdef WIN32 LPSTR lpBuffer; DWORD dwErrorCode = WSAGetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErrorCode, LANG_NEUTRAL, (LPTSTR)&lpBuffer, 0, NULL ); sprintf( strErr, "Socket Error(%ld):%s", dwErrorCode, lpBuffer ); strError = strErr; LocalFree(lpBuffer);#else sprintf( strErr, "socket errno(%d):%s\n", errno, strerror(errno) ); strError = strErr;#endif}bool Socket::InitForIOCP( SOCKET hSocket ){#ifdef WIN32 return 0 == setsockopt( hSocket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&(hSocket), sizeof(hSocket) );#else return true;#endif}//SOCKET Socket::GetSocket(){ return m_hSocket;}void Socket::GetWanAddress( string& strWanIP, int& nWanPort ){ nWanPort = m_nWanPort; strWanIP = m_strWanIP; return;}bool Socket::InitWanAddress(){ assert( INVALID_SOCKET != m_hSocket ); sockaddr_in sockAddr; memset(&sockAddr, 0, sizeof(sockAddr)); socklen_t nSockAddrLen = sizeof(sockAddr); if ( SOCKET_ERROR == getpeername( m_hSocket, (sockaddr*)&sockAddr, &nSockAddrLen ) ) return false; m_nWanPort = ntohs(sockAddr.sin_port); m_strWanIP = inet_ntoa(sockAddr.sin_addr); return true;}void Socket::GetLocalAddress( string& strWanIP, int& nWanPort ){ nWanPort = m_nLocalPort; strWanIP = m_strLocalIP; return;}bool Socket::InitLocalAddress(){ sockaddr_in sockAddr; memset(&sockAddr, 0, sizeof(sockAddr)); socklen_t nSockAddrLen = sizeof(sockAddr); if ( SOCKET_ERROR == getsockname( m_hSocket, (sockaddr*)&sockAddr, &nSockAddrLen )) return false; m_nLocalPort = ntohs(sockAddr.sin_port); m_strLocalIP = inet_ntoa(sockAddr.sin_addr); return true;}/**/bool Socket::Init(protocol nProtocolType){ if ( m_bOpened ) return true; if ( m_hSocket == INVALID_SOCKET ) { m_hSocket = socket( PF_INET, nProtocolType, 0 ); if ( m_hSocket == INVALID_SOCKET ) return false; } m_bOpened = true; return m_bOpened;}/**/bool Socket::Connect( const char *lpszHostAddress, unsigned short nHostPort){ assert( NULL != lpszHostAddress ); sockaddr_in sockAddr; memset(&sockAddr,0,sizeof(sockAddr)); sockAddr.sin_family = AF_INET; sockAddr.sin_addr.s_addr = inet_addr(lpszHostAddress); sockAddr.sin_port = htons( nHostPort ); if ( SOCKET_ERROR != connect(m_hSocket, (sockaddr*)&sockAddr, sizeof(sockAddr)) ) { InitWanAddress(); InitLocalAddress(); return true; } return false;}//bool Socket::StartServer( int nPort ){ if ( !this->Bind( nPort ) ) return false; return this->Listen();}//bool Socket::IsClosed(){ return !m_bOpened;}/**/void Socket::Close(){ if ( INVALID_SOCKET == m_hSocket ) return; if ( m_bOpened ) { closesocket(m_hSocket); m_bOpened = false; } m_hSocket = INVALID_SOCKET; return;}/**/void Socket::Attach(SOCKET hSocket){ m_hSocket = hSocket; m_bBlock = true; m_bOpened = true;// InitWanAddress(); InitLocalAddress();}/**/SOCKET Socket::Detach(){ SOCKET hSocket = m_hSocket; m_hSocket = INVALID_SOCKET; m_bBlock = true; m_bOpened = false;// return hSocket;}/**/int Socket::Receive( void* lpBuf, int nBufLen, bool bCheckDataLength, long lSecond, long lMinSecond ){ if ( TimeOut( lSecond, lMinSecond ) ) return seTimeOut;//³¬Ê± int nResult; int nFlag = 0; if ( bCheckDataLength ) nFlag = MSG_PEEK; nResult = recv(m_hSocket, (char*)lpBuf, nBufLen, nFlag); if ( 0 == nResult ) return seSocketClose;// if ( SOCKET_ERROR != nResult ) return nResult;//ú //socket#ifdef WIN32 int nError = GetLastError(); if ( WSAEWOULDBLOCK == nError ) return 0;// return seError;#else if ( EAGAIN == errno ) return 0;// return seError;#endif}/**/int Socket::Send( const void* lpBuf, int nBufLen, int nFlags ){ int nSendSize = send(m_hSocket, (char*)lpBuf, nBufLen, nFlags); if ( 0 > nSendSize ) {#ifdef WIN32 int nError = GetLastError(); return -1;#else return -1;#endif } if ( nSendSize <= nBufLen ) return nSendSize; return -1;}/**/bool Socket::Bind( unsigned short nPort, char *strIP ){ memset(&m_sockAddr,0,sizeof(m_sockAddr)); m_sockAddr.sin_family = AF_INET; if ( NULL == strIP ) m_sockAddr.sin_addr.s_addr = htonl(INADDR_ANY); else { unsigned long lResult = inet_addr( strIP ); if ( lResult == INADDR_NONE ) return false; m_sockAddr.sin_addr.s_addr = lResult; } m_sockAddr.sin_port = htons((unsigned short)nPort); return (SOCKET_ERROR != bind(m_hSocket, (sockaddr*)&m_sockAddr, sizeof(m_sockAddr)));}/**/bool Socket::Listen( int nConnectionBacklog ){ return (SOCKET_ERROR != listen(m_hSocket, nConnectionBacklog));}/**/bool Socket::Accept(Socket& rConnectedSocket){ assert( INVALID_SOCKET == rConnectedSocket.m_hSocket ); socklen_t sockAddLen = 0; rConnectedSocket.m_hSocket = accept(m_hSocket, NULL, &sockAddLen); if ( INVALID_SOCKET == rConnectedSocket.m_hSocket ) {#ifdef WIN32 if ( WSAEWOULDBLOCK == GetLastError() ) return true;//#else if ( EAGAIN == errno ) return true;//#endif return false;//socket } rConnectedSocket.m_bOpened = true; rConnectedSocket.InitWanAddress(); rConnectedSocket.InitLocalAddress(); return true;}/**/bool Socket::SetSockOpt( int nOptionName, const void* lpOptionValue, int nOptionLen, int nLevel){ return ( SOCKET_ERROR != setsockopt( m_hSocket, nLevel, nOptionName, (char *)lpOptionValue, nOptionLen));}/**/bool Socket::TimeOut( long lSecond, long lMinSecond ){ if ( lSecond <= 0 && lMinSecond <= 0 ) return false; // timeval outtime;// outtime.tv_sec = lSecond; outtime.tv_usec =lMinSecond; int nSelectRet;#ifdef WIN32 FD_SET readfds = { 1, m_hSocket }; nSelectRet=::select( 0, &readfds, NULL, NULL, &outtime ); //#else fd_set readfds; FD_ZERO(&readfds); FD_SET(m_hSocket, &readfds); nSelectRet=::select(m_hSocket+1, &readfds, NULL, NULL, &outtime); //#endif if ( SOCKET_ERROR == nSelectRet ) { return true; } if ( 0 == nSelectRet ) // { return true; } return false;}//bool Socket::WaitData(){ int nSelectRet;#ifdef WIN32 FD_SET readfds = { 1, m_hSocket }; nSelectRet=::select( 0, &readfds, NULL, NULL, NULL ); //#else fd_set readfds; FD_ZERO(&readfds); FD_SET(m_hSocket, &readfds); nSelectRet=::select(m_hSocket+1, &readfds, NULL, NULL, NULL); //#endif if ( SOCKET_ERROR == nSelectRet ) { return false; } if ( 0 == nSelectRet ) // { return false; } return true;}/**/bool Socket::SetSockMode( bool bWait ){#ifdef WIN32 m_bBlock = bWait; unsigned long ul = 1; if ( m_bBlock ) ul = 0; else ul = 1; int ret = ioctlsocket( m_hSocket, FIONBIO, (unsigned long*)&ul ); if ( ret == SOCKET_ERROR ) { return false; }#else m_bBlock = bWait; int flags = fcntl( m_hSocket, F_GETFL, 0 ); // if ( !m_bBlock ) fcntl( m_hSocket, F_SETFL, flags|O_NONBLOCK );// else fcntl( m_hSocket, F_SETFL, flags&(~O_NONBLOCK&0xffffffff) );//#endif return true;}/**/int Socket::SendTo( const char *strIP, int nPort, const void* lpBuf, int nBufLen, int nFlags ){ sockaddr_in sockAddr; memset(&sockAddr,0,sizeof(sockAddr)); sockAddr.sin_family = AF_INET; sockAddr.sin_port = htons(nPort); sockAddr.sin_addr.s_addr = inet_addr(strIP); int ret = sendto( m_hSocket, (const char*)lpBuf, nBufLen, nFlags, (sockaddr*)&sockAddr, sizeof(sockaddr)); if (ret < 0) ret = -1; return ret;}/**/int Socket::ReceiveFrom( char* lpBuf, int nBufLen, string &strFromIP, int &nFromPort, bool bCheckDataLength, long lSecond, long lMinSecond ){ strFromIP = ""; nFromPort = -1; if ( 0 >= nBufLen ) return 0; sockaddr_in sockAddr; socklen_t nAddrLen = sizeof(sockaddr); /* waiting for receive data */ int nResult; int nFlag = 0; while ( true ) { if ( TimeOut( lSecond, lMinSecond ) ) return seTimeOut; if ( bCheckDataLength )nFlag = MSG_PEEK; nResult = recvfrom(m_hSocket, lpBuf, nBufLen, nFlag, (sockaddr*)&sockAddr, &nAddrLen); if ( nAddrLen > 0 ) GetAddress(sockAddr, strFromIP, nFromPort); if ( SOCKET_ERROR == nResult ) // {#ifndef WIN32 if ( EAGAIN == errno ) return 0;// return seError;#else int nError = GetLastError(); if ( 0 == nError )// { if ( MSG_PEEK == nFlag )// { recvfrom(m_hSocket, lpBuf, nBufLen, 0, (sockaddr*)&sockAddr, &nAddrLen); } continue; } if ( WSAEWOULDBLOCK == nError ) return 0;// return seError;#endif } break; } return nResult;}void Socket::GetAddress( const sockaddr_in &sockAddr, string &strIP, int &nPort ){ nPort = ntohs(sockAddr.sin_port); strIP = inet_ntoa(sockAddr.sin_addr);}}//namespace mdk
定义一个客户端的经常用的头文件:
//// mac.h// mac_client//// Created by mac mac on 13-5-8.// Copyright (c) 2013年 __MyCompanyName__. All rights reserved.//#ifndef mac_client_mac_h#define mac_client_mac_h/*1.注意中文标点,编译器不容易察觉2.server 和client端的宏定义大小要统一*//#define MAX_SIZE 1024#define MAX_NAME_LENGTH 64#define MAX_PATH 260 //保持和windows端定义的一样#define MAX_PATH_MAC 256 //苹果的最大长度#define FALSE 0#define TRUE 1#define MAX_SEND_BUFFER 1024*4#define MAX_RECV_BUFFER 1024*4/typedef struct Command //自定义命令结构体{ int order;//命令序号 long datasize; void * hwnd;//窗口句柄 }Command; typedef struct Server_Address //服务器地址{ char strIP[3][MAX_PATH];//服务器ip unsigned int uPort[3] ; //服务器端口 char remark[MAX_NAME_LENGTH];}Server_Address;typedef struct _SYS_INFO //到时候得增加备注{ Command cmd; char remark[MAX_NAME_LENGTH]; //备注 char computer_name[MAX_NAME_LENGTH]; // char user_name[MAX_NAME_LENGTH]; // char sys_version[MAX_NAME_LENGTH]; // char cpu_type[MAX_NAME_LENGTH]; // char host_ip_address[MAX_NAME_LENGTH]; //内网ip char ip_addresss[MAX_NAME_LENGTH]; //外网ip char uuid[MAX_NAME_LENGTH]; //被控端的唯一标识 unsigned int cpu_num; // unsigned int mem_total; // int host_id; //}SYS_INFO;enum { COMMAND_BIGIN = 20000, //命令开始 TOKEN_ONLINE, //上线命令 COMMAND_BREAK, //断开链接 COMMAND_UNINSTALL, //卸载 COMMAND_MODIFY_REMARK, //修改备注/// COMMAND_MANAGER_FILE, //打开文件管理窗口 COMMAND_GET_DIRECTORY, //获取控制端主机根目录下所有文件信息 COMMAND_GET_REQUEST_DIRECTORY, //获取双击请求目录中所有文件信息 COMMAND_SEARCH_FILE, //文件搜索,还没做 COMMAND_WRONG_DIRECTORY, //目录为空或者不可读 COMMAND_DELETE_FILE, //删除文件 COMMAND_FILE_CLOSE, //关闭当前文件管理功能的链接// COMMAND_MANAGER_CMD, //打开cmd管理窗口 TOKEN_CMD_NEXT, //等待下一个命令 COMMAND_SHELL, //控制端请求的shell命令 COMMAND_SHELL_CLOSE, //关闭shell// COMMAND_MANAGER_DOWNLOAD, //打开文件下载功能 TOKEN_DOWNLOAD_SETUP, //控制端发送文件下载连接和uuid COMMAND_GET_FILEDATA, //请求文件数据 TOKEN_SENT_FILEDATA, //发送文件数据 TOKEN_CANT_GET_DATA, //给控制端发送消息文件不可读 COMMAND_MANAGER_UPLOAD, //开启文件上传 TOKEN_UPLOAD_SETUP, //接受文件上传连接 COMMAND_SENT_UPLOAD_DATA, //发送上传文件数据 TOKEN_UPLOAD_DATA, //请求上传文件数据 TOKEN_UPLOAD_COMPLETE, //文件上传完成 COMMAND_RUN_PROGARM, //上传运行的文件 COMMAND_UPLOAD_CLOSE, //关闭上传进程和连接 };#endif
客户端centos下面使用正常,开发环境codeblocks
客户端下载:
服务器windows 7,xp都没有问题,开发环境visual studio 2010
服务端下载:
整体界面:
命令行效果:
文件管理效果:
未完待续
。
。
。