基于C++編寫一個(gè)簡單的服務(wù)器
本文使用上一期寫的反射類,另外我發(fā)現(xiàn)<WinSock2.h>這個(gè)頭文件里有RegisterClass 這個(gè)結(jié)構(gòu),還有typedef RegisterClass RegisterClassW這句話。。。這都能重復(fù),汗。
先寫個(gè)簡易的controller基類繼承反射基類,之后動(dòng)態(tài)調(diào)用的時(shí)候直接使用父類指針,這樣就能根據(jù)映射表來動(dòng)態(tài)使用對(duì)應(yīng)的成員方法。
#pragma once #include "Reflex.h" using namespace myUtil; class CController :public RObject{ };
先寫個(gè)index控制器,這里我是將聲明和實(shí)現(xiàn)分為兩個(gè)文件寫的,不知道為啥分開寫就報(bào)錯(cuò)LNK2005 和 LNK1169,好在找到了解決辦法,在 屬性->配置屬性->鏈接器->命令行中添加 /FORCE:MULTIPLE 即可
這里我給控制器傳入的參數(shù)是兩個(gè)字符串,這是簡易版本,完全可以照著請求報(bào)文和響應(yīng)報(bào)文實(shí)現(xiàn)兩個(gè)類來完成這部分,之后更新吧
接著說,我直接在響應(yīng)報(bào)文中加入了寫的對(duì)應(yīng)的兩個(gè)html頁面,之后用Postman來測試
#pragma once #include "CController.h" using namespace std; class indexController : public CController { public: void show(); void fun(); void add(int& a, int& b); void index(const string& req, string& resp); void title(const string& req, string& resp); int m_age; indexController():m_age(10) {} };
#include "indexController.h" #include <iostream> #include <fstream> using namespace std; void indexController::show() { cout << "hello world show" << endl; } void indexController::fun() { cout << "hello world fun" << endl; } void indexController::add(int& a, int& b) { cout << "hello world add" << endl; } void indexController::index(const string& req, string& resp) { resp = ""; resp.append("HTTP/1.1 200 OK\r\n"); resp.append("content-language:zh-CN"); resp.append("content-type:text/html;charset=utf-8\r\n\r\n"); string text = ""; fstream file; file.open("index.html", ios::in); if (file.fail()) return; while (!file.eof()) { char ch; file.get(ch); text += ch; } resp.append(text); } void indexController::title(const string& req, string& resp) { resp = ""; resp.append("HTTP/1.1 200 OK\r\n"); resp.append("Content-Type:text/html\r\n\r\n"); resp.append("{\"name\":\"title\"}"); }
這是一個(gè)專門用來注冊反射的頭文件,在main中直接調(diào)用宏即可
#pragma once #include "Reflex.h" #include "indexController.h" #define REFLEX_DECLARE \ REGISTER_REFLEX(indexController)\ REGISTER_REFLEX_FIELD(indexController, int, m_age)\ REGISTER_REFLEX_METHOD(indexController, show)\ REGISTER_REFLEX_METHOD(indexController, fun)\ REGISTER_REFLEX_METHOD_ARGS(indexController, add, void, int&, int&)\ REGISTER_REFLEX_METHOD_ARGS(indexController, index, void, string&, string&)\ REGISTER_REFLEX_METHOD_ARGS(indexController, title, void, string&, string&)
這里將映射表設(shè)置為全局變量,可以將服務(wù)作為一個(gè)類,在這個(gè)類中維護(hù)一個(gè)注冊表,再添加一個(gè)方法增加映射,就像springboot中的注釋一樣,下面有反射的測試,可以用函數(shù)名來測試
#include <iostream> #include <string> #include <thread> #include <map> #include <WinSock2.h> #include "Util.h" #include "Singleton.h" #include "macro.h" #include "indexController.h" #pragma comment(lib,"ws2_32.lib") using namespace std; using namespace myUtil; REFLEX_DECLARE //映射表 map<string, string> mapTable = { {"/","index"}, {"/title","title"} }; //用來獲取url vector<string> getStringVectorByChar(const string& source, const char& ch) { vector<string> res; string temp = ""; for (char item : source) { if (item == ch) { res.push_back(temp); temp = ""; } else { temp += item; } } if (temp != "") res.push_back(temp); return res; } void threadFunc(SOCKET ServerSocket) { char ReceiveBuff[BUFSIZ]; char SendBuff[BUFSIZ]; while (true) { SOCKET ClientSocket; SOCKADDR_IN ClientAddr; int ClientAddrLen = sizeof(ClientAddr); ClientSocket = ::accept(ServerSocket, (SOCKADDR*)&ClientAddr, &ClientAddrLen); ZeroMemory(ReceiveBuff, BUFSIZ); recv(ClientSocket, ReceiveBuff, BUFSIZ, 0); cout << "接收自客戶端數(shù)據(jù):\n" << ReceiveBuff << endl; string source(ReceiveBuff); string url = getStringVectorByChar(source, ' ')[1]; //反射使用的地方 Reflex* factory = Singleton<Reflex>::Instance(); CController* a = (CController*)factory->createClass("indexController"); string info = ""; string req = ""; string funName = mapTable[url]; a->Call<void, string&, string&>(funName, req, info); //反射使用結(jié)束 ::send(ClientSocket, info.c_str(), info.size(), 0); closesocket(ClientSocket); } } int main() { //測試反射 //Reflex* factory = Singleton<Reflex>::Instance(); //CController* a = (CController*)factory->createClass("indexController"); //while (1) { // string funName = ""; // cin >> funName; // a->Call<void,int,int>(funName,1,1); //} WORD SocketVersion = MAKEWORD(2, 2); WSADATA wsd; if (WSAStartup(SocketVersion, &wsd) != 0) { cout << "綁定Socket庫失敗" << endl; } SOCKET ServerSocket; ServerSocket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (ServerSocket == INVALID_SOCKET) { cout << "創(chuàng)建服務(wù)器套接字失敗" << endl; WSACleanup(); return -1; } SOCKADDR_IN ServerAddr; ServerAddr.sin_family = AF_INET; ServerAddr.sin_port = htons(9090); ServerAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); int RetVal = ::bind(ServerSocket, (SOCKADDR*)&ServerAddr, sizeof(SOCKADDR_IN)); if (RetVal == SOCKET_ERROR) { cout << "套接字綁定失敗" << endl; closesocket(ServerSocket); WSACleanup(); return -1; } RetVal = ::listen(ServerSocket, 2); if (RetVal == SOCKET_ERROR) { cout << "套接字監(jiān)聽失敗" << endl; closesocket(ServerSocket); WSACleanup(); return -1; } thread th(threadFunc, ServerSocket); th.join(); return 0; }
測試結(jié)果
index
title
以上就是基于C++編寫一個(gè)簡單的服務(wù)器的詳細(xì)內(nèi)容,更多關(guān)于C++服務(wù)器的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
深入探究協(xié)程在C++中的實(shí)現(xiàn)方式
協(xié)程可以被看作是計(jì)算機(jī)程序中的獨(dú)立功能塊,它們在執(zhí)行過程中能夠暫停和恢復(fù),與傳統(tǒng)的函數(shù)調(diào)用相比,協(xié)程更像是一種輕量級(jí)的線程,本文我們將深入探究協(xié)程在C++中的實(shí)現(xiàn)方式,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下2023-12-12MFC中動(dòng)態(tài)創(chuàng)建控件以及事件響應(yīng)實(shí)現(xiàn)方法
這篇文章主要介紹了MFC中動(dòng)態(tài)創(chuàng)建控件以及事件響應(yīng)實(shí)現(xiàn)方法,詳細(xì)講解了MFC中動(dòng)態(tài)創(chuàng)建控件以及事件響應(yīng)的概念與實(shí)現(xiàn)方法,具有一定的實(shí)用價(jià)值,需要的朋友可以參考下2014-10-10C++實(shí)現(xiàn)LeetCode(10.正則表達(dá)式匹配)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(10.正則表達(dá)式匹配),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07vscode編譯運(yùn)行c語言報(bào)錯(cuò)亂碼的解決
本文主要介紹了vscode編譯運(yùn)行c語言報(bào)錯(cuò)亂碼,文中通過圖文介紹的的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-07-07