标签:
其实就只是对网络底层的一个封装,一些回调全部都已经封装好,直接指定相应的回调函数就可以对收到的数据包进行处理。
个人觉得该网络库比较方便的地方就是可以直接将所有自定义及C++标准库容器直接发送到服务端,而原始的C函数发送时连续存储的内存。
注意,该库使用C11编译,所以客户端必须支持C11,废话不多说下面直接看使用demo。
协议定义(protocols.h)
1 #pragma once 2 #include "protocolbase.h" 3 4 5 //客户端请求登录 6 class QLogin :public Net::ProtocolBase 7 { 8 public: 9 QLogin() = default; 10 ~QLogin() = default; 11 12 Serialize(QLogin) 13 { 14 ar(uClientId, strUsername, strPassword); 15 } 16 17 Net::UInt32 uClientId; 18 std::string strUsername; 19 std::string strPassword; 20 }; 21 22 //客户端请求数据 23 class QData :public Net::ProtocolBase 24 { 25 public: 26 QData() = default; 27 ~QData() = default; 28 29 Serialize(QData) 30 { 31 32 } 33 }; 34 35 36 //响应客户端登录 37 class RLogin :public Net::ProtocolBase 38 { 39 public: 40 RLogin() = default; 41 ~RLogin() = default; 42 43 Serialize(RLogin) 44 { 45 ar(strErrorInfo); 46 } 47 48 std::string strErrorInfo; 49 }; 50 51 class CustomData 52 { 53 public: 54 CustomData() = default; 55 ~CustomData() = default; 56 57 Serialize(CustomData) 58 { 59 ar(nData, fData, dData, shData); 60 } 61 62 int nData; 63 float fData; 64 double dData; 65 short shData; 66 }; 67 68 69 //响应客户端请求数据 70 class RData :public Net::ProtocolBase 71 { 72 public: 73 RData() = default; 74 ~RData() = default; 75 76 Serialize(RData) 77 { 78 ar(strNickname, bSex, uAge, strEmail, vData, mData, customData); 79 } 80 81 std::string strNickname; 82 bool bSex; 83 Net::UInt8 uAge; 84 std::string strEmail; 85 std::vector<std::string> vData; 86 std::map<std::string,std::pair<int,float> > mData; 87 CustomData customData; 88 };
main.cpp
#include "socketserver.h" #include "socketclient.h" #include "protocols.h" #include <iostream> class ServerSocketSession :public Net::SocketSession { public: ServerSocketSession() = default; ~ServerSocketSession() { } ServerSocketSession(const ServerSocketSession&) = delete; ServerSocketSession& operator = (const ServerSocketSession&) = delete; //响应用户登录 void userLogin(std::shared_ptr<QLogin> r) { auto result = std::make_shared<RLogin>(); if (r->uClientId == 123456 && r->strUsername == "123456" && r->strPassword == "123456") { result->strErrorInfo = "LoginSucceed"; } else { result->strErrorInfo = "LoginFailure"; } send(result); } //响应用户请求详细数据 void userData(std::shared_ptr<QData> r) { auto result = std::make_shared<RData>(); result->strNickname = "winter"; result->bSex = true; result->strEmail = "winter@gmail.com"; result->uAge = 100; result->mData.emplace("m1",std::make_pair(1111,111.111f)); result->mData.emplace("m2", std::make_pair(2222, 222.222f)); result->mData.emplace("m3", std::make_pair(3333, 333.333f)); result->vData.push_back("v1"); result->vData.push_back("v2"); result->vData.push_back("v3"); result->vData.push_back("v4"); result->customData.dData = -10000000.000001f; result->customData.fData = 100000.00002f; result->customData.nData = -100000; result->customData.shData = -100; send(result); } }; class ClientSocketSession { public: ClientSocketSession() :m_socketClient("127.0.0.1", 6691, true) { m_socketClient.registerProtocol(&ClientSocketSession::onUserLogin, this); m_socketClient.registerProtocol(&ClientSocketSession::onUserData, this); m_socketClient.registerProtocol(&ClientSocketSession::onSocketEvent, this); m_socketClient.connect(); } ~ClientSocketSession() = default; ClientSocketSession(const ClientSocketSession&) = delete; ClientSocketSession& operator = (const ClientSocketSession&) = delete; void update(){ m_socketClient.update(); } void onSocketEvent(std::shared_ptr<Net::SocketEvent> r, Net::SocketClient::ErrorCode e) { if (e == Net::SocketClient::ErrorCode::kSucceed && r->getEvent() == Net::SocketEvent::Event::kConnect) { std::cout << "Connect succeed! " << r->getInfo() << std::endl; auto qlogin = std::make_shared<QLogin>(); qlogin->uClientId = 11111; qlogin->strUsername = "11111"; qlogin->strPassword = "11111"; m_socketClient.send(qlogin); } else { if (r->getEvent() == Net::SocketEvent::Event::kConnect) { std::cout << "Connect: "<< r->getInfo() << std::endl; } else { std::cout << "DisConnect: " << r->getInfo() << std::endl; } } } void onUserLogin(std::shared_ptr<RLogin> r, Net::SocketClient::ErrorCode e) { if (r->strErrorInfo == "LoginSucceed") { auto qdata = std::make_shared<QData>(); for (size_t i = 0; i < 10; i++) { m_socketClient.send(qdata); } } else if (r->strErrorInfo == "LoginFailure") { auto qlogin = std::make_shared<QLogin>(); qlogin->uClientId = 123456; qlogin->strUsername = "123456"; qlogin->strPassword = "123456"; m_socketClient.send(qlogin); } } void onUserData(std::shared_ptr<RData> r, Net::SocketClient::ErrorCode e) { std::cout << "Nickname: " << r->strNickname << std::endl; std::cout << "Sex: " << (r->bSex ? "true": "false") << std::endl; std::cout << "Age: " << (int)r->uAge << std::endl; std::cout << "Email: " << r->strEmail << std::endl; for (auto data : r->vData) { std::cout << "vData: " << data << std::endl; } for (auto data : r->mData) { std::cout << "vData:" << data.first << ":" << data.second.first << ":" << data.second.second << std::endl; } std::cout << "customData.nData: " << r->customData.nData << std::endl; std::cout << "customData.fData: " << r->customData.fData << std::endl; std::cout << "customData.dData: " << r->customData.dData << std::endl; std::cout << "customData.shData: " << r->customData.shData << std::endl; } private: Net::SocketClient m_socketClient; }; int wmain(int argc, wchar_t* argv[]) { auto server = Net::SocketServer::createInstance<ServerSocketSession>("127.0.0.1", 6691, 1,true); server->registerProtocol(&ServerSocketSession::userLogin); server->registerProtocol(&ServerSocketSession::userData); ClientSocketSession clientSession; //一个简单的主循环 bool bExit(true); while (bExit) { std::this_thread::sleep_for(std::chrono::milliseconds(50)); //在客户端的每一帧需要调用以下函数。 clientSession.update(); } return 0; }
下面是完整demo,使用vs2013编译
http://files.cnblogs.com/files/winter-yu/libSocket.zip
分享一个自己使用了很久的C++网络封装库,包含服务端和客户端,支持跨平台
标签:
原文地址:http://www.cnblogs.com/winter-yu/p/4688481.html