<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
本文使用上一期寫的反射類,另外我發現<WinSock2.h>這個標頭檔案裡有RegisterClass 這個結構,還有typedef RegisterClass RegisterClassW這句話。。。這都能重複,汗。
先寫個簡易的controller基礎類別繼承反射基礎類別,之後動態呼叫的時候直接使用父類別指標,這樣就能根據對映表來動態使用對應的成員方法。
#pragma once #include "Reflex.h" using namespace myUtil; class CController :public RObject{ };
先寫個index控制器,這裡我是將宣告和實現分為兩個檔案寫的,不知道為啥分開寫就報錯LNK2005 和 LNK1169,好在找到了解決辦法,在 屬性->設定屬性->連結器->命令列中新增 /FORCE:MULTIPLE 即可
這裡我給控制器傳入的引數是兩個字串,這是簡易版本,完全可以照著請求報文和響應報文實現兩個類來完成這部分,之後更新吧
接著說,我直接在響應報文中加入了寫的對應的兩個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 OKrn"); resp.append("content-language:zh-CN"); resp.append("content-type:text/html;charset=utf-8rnrn"); 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 OKrn"); resp.append("Content-Type:text/htmlrnrn"); resp.append("{"name":"title"}"); }
這是一個專門用來註冊反射的標頭檔案,在main中直接呼叫宏即可
#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&)
這裡將對映表設定為全域性變數,可以將服務作為一個類,在這個類中維護一個登入檔,再新增一個方法增加對映,就像springboot中的註釋一樣,下面有反射的測試,可以用函數名來測試
#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 << "接收自使用者端資料: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); //反射使用結束 ::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 << "建立伺服器通訊端失敗" << 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 << "通訊端監聽失敗" << endl; closesocket(ServerSocket); WSACleanup(); return -1; } thread th(threadFunc, ServerSocket); th.join(); return 0; }
測試結果
index
title
以上就是基於C++編寫一個簡單的伺服器的詳細內容,更多關於C++伺服器的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45