这篇文章主要讲解了“基于C++怎么编写一个简单的服务器”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“基于C++怎么编写一个简单的服务器”吧!
先写个简易的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 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中直接调用宏即可
#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++怎么编写一个简单的服务器这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://blog.csdn.net/weixin_43891802/article/details/129516506