本文共 10149 字,大约阅读时间需要 33 分钟。
From:http://cn.cocos2d-x.org/tutorial/show?id=2193
Socket基类
包括Socket的初始化,主要是Windows上,在Android上就不需要了。
如果平台为Windows,则需要初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | SocketBase::SocketBase() { _bInitSuccess = false ; # if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) WORD wVersionRequested; wVersionRequested = MAKEWORD(2, 0); WSADATA wsaData; int nRet = WSAStartup(wVersionRequested, &wsaData); if (nRet != 0) { fprintf (stderr, "Initilize Error!\n" ); return ; } _bInitSuccess = true ; #endif } |
当然析构时也要释放资源
1 2 3 4 5 6 7 8 9 | SocketBase::~SocketBase() { # if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) if (_bInitSuccess) { WSACleanup(); } #endif } |
因为Windows的socket()返回的socket句柄为SOCKET(UINT_PTR)与Android的socket()返回的socket句柄int, 类型不一样,所以都定义为HSocket。
对于服务端和客户端都有关闭连接,所以基类就实现共同的。
1 2 3 4 5 6 7 8 | void SocketBase::closeConnect(HSocket socket) { # if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) close(socket); #elif (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) closesocket(socket); #endif } |
当执行socket()出错时,Windows返回SOCKET_ERROR, Android返回<0,所以实现error()
1 2 3 4 5 6 7 8 | bool SocketBase::error(HSocket socket) { # if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) return socket == SOCKET_ERROR; #elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) return socket < 0; #endif } |
SocketBase.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | #ifndef __SOCKET_BASE_H__ #define __SOCKET_BASE_H__ #include "cocos2d.h" #include <list> #include <thread> USING_NS_CC; // 对于windows平台 #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) #include <WinSock2.h> #pragma comment(lib, "WS2_32.lib") #define HSocket SOCKET // 对于android平台 #elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) #include <arpa/inet.h> // for inet_** #include <netdb.h> // for gethost** #include <netinet/in.h> // for sockaddr_in #include <sys/types.h> // for socket #include <sys/socket.h> // for socket #include <unistd.h> #include <stdio.h> // for printf #include <stdlib.h> // for exit #include <string.h> // for bzero #define HSocket int #endif class SocketBase : public Ref { public : SocketBase(); ~SocketBase(); protected : void closeConnect(HSocket socket); bool error(HSocket socket); protected : std::mutex _mutex; private : bool _bInitSuccess; }; #endif |
初始化服务端
向指定客户端发送消息
1 | void sendMessage(HSocket socket, const char * data, int count); |
向所有客户端发送消息
1 | void sendMessage( const char * data, int count); |
当服务端开启后的回调函数
1 | std::function< void ( const char * ip)> onStart; |
当有新连接时的回调函数
1 | std::function< void (HSocket socket)> onNewConnection; |
当有消息时的回调函数
1 | std::function< void ( const char * data, int count)> onRecv; |
当有客户端断开连接时的回调函数
1 | std::function< void (HSocket socket)> onDisconnect; |
SocketServer.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #ifndef __SOCKET_SERVER_H__ #define __SOCKET_SERVER_H__ #include "SocketBase.h" class SocketServer : public SocketBase { public : static SocketServer* create(); SocketServer(); ~SocketServer(); bool startServer(); void sendMessage(HSocket socket, const char * data, int count); void sendMessage( const char * data, int count); std::function< void ( const char * ip)> onStart; std::function< void (HSocket socket)> onNewConnection; std::function< void ( const char * data, int count)> onRecv; std::function< void (HSocket socket)> onDisconnect; private : bool initServer(); void acceptClient(); void acceptFunc(); void newClientConnected(HSocket socket); void recvMessage(HSocket socket); private : HSocket _socketServer; private : std::list<HSocket> _clientSockets; }; #endif |
SocketServer.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | #include "SocketServer.h" SocketServer* SocketServer::create() { auto server = new SocketServer; return server; } SocketServer::SocketServer() : _socketServer(0), onRecv(nullptr), onStart(nullptr), onNewConnection(nullptr) { } SocketServer::~SocketServer() { _clientSockets.clear(); if (_socketServer) { this ->closeConnect(_socketServer); } }; bool SocketServer::startServer() { if (!initServer()) { return false ; } return true ; } bool SocketServer::initServer() { if (_socketServer != 0) { this ->closeConnect(_socketServer); } _socketServer = socket(AF_INET, SOCK_STREAM, 0); if (error(_socketServer)) { log ( "socket error!" ); _socketServer = 0; return false ; } do { struct sockaddr_in sockAddr; memset (&sockAddr, 0, sizeof (sockAddr)); sockAddr.sin_family = AF_INET; sockAddr.sin_port = htons(8000); sockAddr.sin_addr.s_addr = htonl(INADDR_ANY); int ret = 0; ret = bind(_socketServer, ( const sockaddr*)&sockAddr, sizeof (sockAddr)); if (ret < 0) { log ( "bind error!" ); break ; } ret = listen(_socketServer, 5); if (ret < 0) { log ( "listen error!" ); break ; } // start char hostName[256]; gethostname(hostName, sizeof (hostName)); struct hostent* hostInfo = gethostbyname(hostName); char * ip = inet_ntoa(*( struct in_addr *)*hostInfo->h_addr_list); this ->acceptClient(); if (onStart != nullptr) { log ( "start server!" ); onStart(ip); } return true ; } while ( false ); this ->closeConnect(_socketServer); _socketServer = 0; return false ; } void SocketServer::acceptClient() { std:: thread th(&SocketServer::acceptFunc, this ); th.detach(); } void SocketServer::acceptFunc() { int len = sizeof (sockaddr); struct sockaddr_in sockAddr; while ( true ) { HSocket clientSock = accept(_socketServer, (sockaddr*)&sockAddr, &len); if (error(clientSock)) { log ( "accept error!" ); break ; } this ->newClientConnected(clientSock); } } void SocketServer::newClientConnected(HSocket socket) { log ( "new connect!" ); _clientSockets.push_back(socket); std:: thread th(&SocketServer::recvMessage, this , socket); th.detach(); if (onNewConnection != nullptr) { onNewConnection(socket); } } void SocketServer::recvMessage(HSocket socket) { char buff[1024]; int ret = 0; while ( true ) { ret = recv(socket, buff, sizeof (buff), 0); if (ret < 0) { log ( "recv(%d) error!" , socket); _mutex.lock(); this ->closeConnect(socket); _clientSockets. remove (socket); if (onDisconnect != nullptr) { onDisconnect(socket); } _mutex.unlock(); break ; } else { buff[ret] = 0; log ( "recv msg : %s" , buff); if (ret > 0 && onRecv != nullptr) { onRecv(buff, ret); } } } } void SocketServer::sendMessage(HSocket socket, const char * data, int count) { for (auto& sock : _clientSockets) { if (sock == socket) { int ret = send(socket, data, count, 0); if (ret < 0) { log ( "send error!" ); } break ; } } } void SocketServer::sendMessage( const char * data, int count) { for (auto& socket : _clientSockets) { int ret = send(socket, data, count, 0); if (ret < 0) { log ( "send error!" ); } } } |
连接服务端
1 | bool connectServer( const char * serverIP, unsigned short port); |
向服务端发送消息
1 | void sendMessage( const char * data, int count); |
接受服务端数据的回调函数
1 | std::function< void ( const char * data, int count)> onRecv; |
断开连接的回调函数
1 | std::function< void ()> onDisconnect; |
SocketClient.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #ifndef __SOCKET_CLIENT_H__ #define __SOCKET_CLIENT_H__ #include "SocketBase.h" class SocketClient : public SocketBase { public : SocketClient( void ); ~SocketClient( void ); bool connectServer( const char * serverIP, unsigned short port); void sendMessage( const char * data, int count); std::function< void ( const char * data, int count)> onRecv; std::function< void ()> onDisconnect; private : bool initClient(); void recvMessage(); private : HSocket _socketServer; HSocket _socektClient; }; #endif |
SocketClient.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | #include "SocketClient.h" SocketClient::SocketClient( void ) : onRecv(nullptr), _socektClient(0) { } SocketClient::~SocketClient( void ) { if (_socektClient != 0) { _mutex.lock(); this ->closeConnect(_socektClient); _mutex.unlock(); } } bool SocketClient::initClient() { if (_socektClient != 0) { _mutex.lock(); this ->closeConnect(_socektClient); _mutex.unlock(); } _socektClient = socket(AF_INET, SOCK_STREAM, 0); if (error(_socketServer)) { log ( "init client error!" ); _socektClient = 0; return false ; } return true ; } bool SocketClient::connectServer( const char * serverIP, unsigned short port) { if (! this ->initClient()) { return false ; } struct sockaddr_in serverAddr; memset (&serverAddr, 0, sizeof ( struct sockaddr_in)); serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(port); serverAddr.sin_addr.s_addr = inet_addr(serverIP); int ret = 0; ret = connect(_socektClient, ( struct sockaddr*)&serverAddr, sizeof ( struct sockaddr)); if (ret < 0) { this ->closeConnect(_socektClient); _socektClient = 0; return false ; } std:: thread recvThread(&SocketClient::recvMessage, this ); recvThread.detach(); return true ; } void SocketClient::recvMessage() { char recvBuf[1024]; int ret = 0; while ( true ) { ret = recv(_socektClient, recvBuf, sizeof (recvBuf), 0); if (ret < 0) { log ( "recv error" ); break ; } if (ret > 0 && onRecv != nullptr) { onRecv(recvBuf, ret); } } _mutex.lock(); this ->closeConnect(_socektClient); if (onDisconnect != nullptr) { onDisconnect(); } _socektClient = 0; _mutex.unlock(); } void SocketClient::sendMessage( const char * data, int count) { if (_socektClient != 0) { int ret = send(_socektClient, data, count, 0); if (ret < 0) { log ( "send error!" ); } } } |
转载地址:http://xlqgx.baihongyu.com/