封装Client
文章目錄
- 1 封裝Client
- 1.1 概述
- 1.2 封裝Client
1 封裝Client
1.1 概述
為了更方便的使用client的功能,我們這里把Client相關代碼進行封裝。
1.2 封裝Client
封裝后主要有如下三個文件:
MessageHeader.hpp:
EasyTcpClient.hpp:
#ifndef _EasyTcpClient_hpp_ #define _EasyTcpClient_hpp_#ifdef _WIN32#define WIN32_LEAN_AND_MEAN#include<windows.h>#include<WinSock2.h>#pragma comment(lib,"ws2_32.lib") #else#include<unistd.h> //uni std#include<arpa/inet.h>#include<string.h>#define SOCKET int#define INVALID_SOCKET (SOCKET)(~0)#define SOCKET_ERROR (-1) #endif #include <stdio.h> #include "MessageHeader.hpp"class EasyTcpClient {SOCKET _sock; public:EasyTcpClient(){_sock = INVALID_SOCKET;}virtual ~EasyTcpClient(){Close();}//初始化socketvoid InitSocket(){ #ifdef _WIN32//啟動Windows socket 2.x環(huán)境WORD ver = MAKEWORD(2, 2);WSADATA dat;WSAStartup(ver, &dat); #endifif (INVALID_SOCKET != _sock){printf("<socket=%d>關閉舊連接...\n", _sock);Close();}_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (INVALID_SOCKET == _sock){printf("錯誤,建立Socket失敗...\n");}else {printf("建立Socket=<%d>成功...\n", _sock);}}//連接服務器int Connect(const char* ip,unsigned short port){if (INVALID_SOCKET == _sock){InitSocket();}// 2 連接服務器 connectsockaddr_in _sin = {};_sin.sin_family = AF_INET;_sin.sin_port = htons(port); #ifdef _WIN32_sin.sin_addr.S_un.S_addr = inet_addr(ip); #else_sin.sin_addr.s_addr = inet_addr(ip); #endifprintf("<socket=%d>正在連接服務器<%s:%d>...\n", _sock, ip, port);int ret = connect(_sock, (sockaddr*)&_sin, sizeof(sockaddr_in));if (SOCKET_ERROR == ret){printf("<socket=%d>錯誤,連接服務器<%s:%d>失敗...\n",_sock, ip, port);}else {printf("<socket=%d>連接服務器<%s:%d>成功...\n",_sock, ip, port);}return ret;}//關閉套節(jié)字closesocketvoid Close(){if (_sock != INVALID_SOCKET){ #ifdef _WIN32closesocket(_sock);//清除Windows socket環(huán)境WSACleanup(); #elseclose(_sock); #endif_sock = INVALID_SOCKET;}}//處理網(wǎng)絡消息bool OnRun(){if (isRun()){fd_set fdReads;FD_ZERO(&fdReads);FD_SET(_sock, &fdReads);timeval t = { 0,0 };int ret = select(_sock + 1, &fdReads, 0, 0, &t); if (ret < 0){printf("<socket=%d>select任務結束1\n", _sock);Close();return false;}if (FD_ISSET(_sock, &fdReads)){FD_CLR(_sock, &fdReads);if (-1 == RecvData(_sock)){printf("<socket=%d>select任務結束2\n", _sock);Close();return false;}}return true;}return false;}//是否工作中bool isRun(){return _sock != INVALID_SOCKET;}//接收數(shù)據(jù) 處理粘包 拆分包int RecvData(SOCKET _cSock){//緩沖區(qū)char szRecv[4096] = {};// 5 接收客戶端數(shù)據(jù)int nLen = (int)recv(_cSock, szRecv, sizeof(DataHeader), 0);DataHeader* header = (DataHeader*)szRecv;if (nLen <= 0){printf("<socket=%d>與服務器斷開連接,任務結束。\n",_cSock);return -1;}recv(_cSock, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), 0);OnNetMsg(header);return 0;}//響應網(wǎng)絡消息void OnNetMsg(DataHeader* header){switch (header->cmd){case CMD_LOGIN_RESULT:{LoginResult* login = (LoginResult*)header;printf("<socket=%d>收到服務端消息:CMD_LOGIN_RESULT,數(shù)據(jù)長度:%d\n", _sock, login->dataLength);}break;case CMD_LOGOUT_RESULT:{LogoutResult* logout = (LogoutResult*)header;printf("<socket=%d>收到服務端消息:CMD_LOGOUT_RESULT,數(shù)據(jù)長度:%d\n", _sock, logout->dataLength);}break;case CMD_NEW_USER_JOIN:{NewUserJoin* userJoin = (NewUserJoin*)header;printf("<socket=%d>收到服務端消息:CMD_NEW_USER_JOIN,數(shù)據(jù)長度:%d\n", _sock, userJoin->dataLength);}break;}}//發(fā)送數(shù)據(jù)int SendData(DataHeader* header){if (isRun() && header){return send(_sock, (const char*)header, header->dataLength, 0);}return SOCKET_ERROR;} private:};#endifclient.cpp:
#include "EasyTcpClient.hpp" #include<thread>void cmdThread(EasyTcpClient* client) {while (true){char cmdBuf[256] = {};scanf("%s", cmdBuf);if (0 == strcmp(cmdBuf, "exit")){client->Close();printf("退出cmdThread線程\n");break;}else if (0 == strcmp(cmdBuf, "login")){Login login;strcpy(login.userName, "lyd");strcpy(login.PassWord, "lydmm");client->SendData(&login);}else if (0 == strcmp(cmdBuf, "logout")){Logout logout;strcpy(logout.userName, "lyd");client->SendData(&logout);}else {printf("不支持的命令。\n");}} }int main() {EasyTcpClient client1;client1.Connect("192.168.74.1", 4567);EasyTcpClient client2;client2.Connect("192.168.74.136", 4567);EasyTcpClient client3;client3.Connect("192.168.74.134", 4567); /*//啟動UI線程std::thread t1(cmdThread, &client1);t1.detach();std::thread t2(cmdThread, &client2);t2.detach();std::thread t3(cmdThread, &client3);t3.detach(); */Login login;strcpy(login.userName, "lyd");strcpy(login.PassWord, "lydmm");while (client1.isRun() || client2.isRun() || client3.isRun()){client1.OnRun();client2.OnRun();client3.OnRun();client1.SendData(&login);client2.SendData(&login);client3.SendData(&login);//printf("空閑時間處理其它業(yè)務..\n");//Sleep(1000);}client1.Close();client2.Close();client3.Close();printf("已退出。\n");getchar();return 0; }參考資料:
總結
- 上一篇: 表索引
- 下一篇: QSZ92式5.8mm手枪