首先,我们可以用到这个开源的开发包:
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的并发算法,保证并发效率 欢迎大家共同学习使用。
http://download.csdn.net/detail/wangyaninglm/8260299
或者是这里:
https://github.com/huoyu820125/Micro-Development-Kit
我们写客户端的时候可以用到里面 的socket类
socket.h如下:
// Socket.h: interface for the Socket class. // ////////////////////////////////////////////////////////////////////// /*********************************************************************** ************************************************************************/ #ifndef MDK_SOCKET_H #define MDK_SOCKET_H #include <iostream> using namespace std; #ifdef WIN32 #include <windows.h> #define socklen_t int #else #include <errno.h> #include <string.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/wait.h> #include <fcntl.h> #include <arpa/inet.h> #include <sys/select.h> #include <sys/types.h> #define INVALID_SOCKET -1 #define SOCKET_ERROR -1 #define closesocket close typedef int SOCKET; #endif #include <time.h> #include <assert.h> #include <string> 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 <stdio.h> #include <iostream> #include "Socket.h" #ifdef WIN32 //#include <windows.h> #pragma comment ( lib, "ws2_32.lib" ) #endif using 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
客户端下载:
http://download.csdn.net/detail/wangyaninglm/8326249
服务器windows 7,xp都没有问题,开发环境visual studio 2010
服务端下载:
http://download.csdn.net/detail/wangyaninglm/8326321
整体界面:
命令行效果:
文件管理效果:
未完待续
。
。
。