本文使用上一期写的反射类,另外我发现<WinSock2.h>这个头文件里有RegisterClass 这个结构,还有typedef RegisterClass RegisterClassW这句话。。。这都能重复,汗。
先写个简易的controller基类继承反射基类,之后动态调用的时候直接使用父类指针,这样就能根据映射表来动态使用对应的成员方法。
1
2
3
4
5
|
#pragma once #include "Reflex.h" using namespace myUtil; class CController : public RObject{ }; |
先写个index控制器,这里我是将声明和实现分为两个文件写的,不知道为啥分开写就报错LNK2005 和 LNK1169,好在找到了解决办法,在 属性->配置属性->链接器->命令行中添加 /FORCE:MULTIPLE 即可
这里我给控制器传入的参数是两个字符串,这是简易版本,完全可以照着请求报文和响应报文实现两个类来完成这部分,之后更新吧
接着说,我直接在响应报文中加入了写的对应的两个html页面,之后用Postman来测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#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) {} }; |
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
|
#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\"}" ); } |
这是一个专门用来注册反射的头文件,在main中直接调用宏即可
1
2
3
4
5
6
7
8
9
10
11
|
#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中的注释一样,下面有反射的测试,可以用函数名来测试
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
|
#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++服务器的资料请关注服务器之家其它相关文章!
原文链接:https://blog.csdn.net/weixin_43891802/article/details/129516506