C++ 手撸简易服务器(完善版本)

本文没有带反射部分内容,可以看我之前发的

Server.h

#pragma once

#include <string>
#include <iostream>
#include <thread>
#include <unordered_map>
using namespace std;
#ifndef _SERVER_
#define _SERVER_

#include <winsock.h>
#include "Net.h"
#include "Util.h"
#pragma comment(lib,"ws2_32.lib")

NAME_SPACE_START(myUtil)

#define SERVER_ADDR "127.0.0.1"
#define SERVER_PORT 8080

class Server {
public:
    Server();
    Server(const std::string& addr = SERVER_ADDR, const int& port = SERVER_PORT);
    ~Server() {}
public:
    bool listen(const int& maxConnect = 1);
    void setRoute(const string& url, const string& className, const string& classFunName);
    void runRoute(const Request& req, Response* resp);
    void setInterceptor(const string& url, const string& InterceptorName);
    void close();
protected:
    bool Init();
    void threadFunc(SOCKET m_server);
    int sendTelegram(const SOCKET& accept, const string& info, int flags);
private:
    SOCKET m_server;
    SOCKADDR_IN m_add_in;
    //thread listenThread;
    int connectCount{ 0 };
    unordered_map<string, pair<string, string>> routeMap;
    unordered_map<string, string> interceptorMap;
    IniHelper iniHelper;
};

NAME_SPACE_END()
#endif //!_SERVER_

Server.cpp

#include "Server.h"
#include <minwindef.h>
#include <string>
#include <winsock.h>
#include <iostream>
#include <thread>
#include <fstream>
#include "Net.h"
#include "Util.h"
#include "Reflex.h"
#include "CController.h"
#include "Interceptor.h"
using namespace std;

NAME_SPACE_START(myUtil)

Server::Server()
{
    m_add_in.sin_family = AF_INET;
    m_add_in.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    m_add_in.sin_port = htons(SERVER_PORT);
}

Server::Server(const std::string& addr, const int& port)
{
    m_add_in.sin_family = AF_INET;
    m_add_in.sin_addr.S_un.S_addr = inet_addr(addr.c_str());
    m_add_in.sin_port = htons(port);
}

bool Server::listen(const int& maxConnect)
{
    if (!Init()) {
        return false;
    }
    m_server = socket(AF_INET, SOCK_STREAM, 0);
    if (::bind(m_server, (sockaddr*)&m_add_in, sizeof(SOCKADDR)) == SOCKET_ERROR) {
        WSACleanup();
        return false;
    }
    if (::listen(m_server, maxConnect) < 0) {
        WSACleanup();
        return false;
    }
    thread listenThread(&Server::threadFunc, this, m_server);
    listenThread.join();
    return true;
}

void Server::setRoute(const string& url, const string& className, const string& classFunName)
{
    routeMap.insert(pair<string, pair<string, string>>(url, pair<string, string>(className, classFunName)));
}

void Server::runRoute(const Request& req, Response* resp)
{
    string url = req.getRequestStatus().Url;
    Reflex* factory = myUtil::Singleton<Reflex>::Instance();
    string interceptorName = "";
    string res = "";
    string content = "";
    //拦截器
    //先去拦截器映射表中寻找类名,没有的话默认使用基类
    auto interceptorIt = interceptorMap.find(url);
    if (interceptorIt != interceptorMap.end()) interceptorName = interceptorIt->second;
    Interceptor* inter = (Interceptor*)factory->createClass(interceptorName);
    if (inter == nullptr) inter = new Interceptor();
    if (inter->preHandle(req, *resp)) {
        //反射
        auto it = routeMap.find(url);
        if (it != routeMap.end()) {
            CController* cont = (CController*)factory->createClass(it->second.first);
            res = cont->Call<string, Request, Response*>(it->second.second, req, resp);
        }
        //反射结束
    }
    else {
        resp->setResponseStatus("HTTP", 1, 1, 404, "Forbidden");
    }
    if (url.find("favicon.ico") != string::npos) {
        content = getFile(iniHelper.getIniConfig("staticResource", "favicon_path", "./favicon.ico"));
        resp->setResponseHead("content-type", "image/x-icon");
    }
    else if(res != "") {
        try {
            content = getFile(res);
        }
        catch(exception ex){
            content = ex.what();
        }
    }
    resp->setResponseContent(content);
    auto list = resp->getCookie();
    for (auto item : list) {
        resp->setResponseHead("Set-Cookie", item.toString());
    }
    resp->setResponseHead("content-length", to_string(content.size()));
    resp->setResponseHead("Server", "C++MVC");
    inter->postHandle(req, *resp);
}

void Server::setInterceptor(const string& url, const string& InterceptorName)
{
    interceptorMap.insert(pair<string, string>(url, InterceptorName));
}

void Server::close()
{
    closesocket(m_server);
    WSACleanup();
}

bool Server::Init()
{
    WORD ver = MAKEWORD(2, 2);
    WSADATA wsadata;
    int errFlag = -1;
    errFlag = WSAStartup(ver, &wsadata);
    if (errFlag != 0) return false;
    //检测版本号
    if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2) {
        WSACleanup();
        return false;
    }
    return true;

}
void Server::threadFunc(SOCKET m_server)
{
    while (1) {
        SOCKADDR_IN m_acc_in;
        int len = sizeof(SOCKADDR);
        SOCKET m_accept = accept(m_server, (sockaddr*)&m_acc_in, &len);
        if (m_accept == SOCKET_ERROR) {
            continue;
        }
        int recv_len = 0;
        char recv_buf[10000];
        recv_len = recv(m_accept, recv_buf, 10000, 0);
        
        //char 转 wchar
        int  unicodeLen = ::MultiByteToWideChar(CP_UTF8, 0, recv_buf, -1, NULL, 0);
        wchar_t* pUnicode = new  wchar_t[unicodeLen];
        memset(pUnicode, 0, unicodeLen * sizeof(wchar_t));
        ::MultiByteToWideChar(CP_UTF8, 0, recv_buf, -1, (LPWSTR)pUnicode, unicodeLen);
        wstring  rt = pUnicode;
        //重设大小
        char* pAscii = new char[recv_len];
        memset(pAscii, 0, sizeof(char) * recv_len);
        strncpy(pAscii, recv_buf, recv_len);
        string lrt(pAscii);
        //解析请求
        Request req(lrt);
        Response resp;
        runRoute(req, &resp);
        cout << "请求地址:" << req.getRequestStatus().Url << endl;
        sendTelegram(m_accept, resp.toString(), 0);
        closesocket(m_accept);
    }
}

int Server::sendTelegram(const SOCKET& accept, const string& info, int flags)
{
    int res = send(accept, info.c_str(), info.size(), flags);
    return res;
}

NAME_SPACE_END()

Interceptor.h

#pragma once
#include "Net.h"
#include "Reflex.h"
using namespace myUtil;
#ifndef _INTERCEPTOR_
#define _INTERCEPTOR_

class Interceptor : public RObject {
public:
    virtual bool preHandle(const Request& request, const Response& response) { return true; }

    virtual void postHandle(const Request& request, const Response& response) {}

    virtual void afterCompletion(const Request& request, const Response& response) {}
};

#endif //!_INTERCEPTOR_

indexInterceptor.h

#pragma once
#include "Interceptor.h"
class IndexInterceptor : public Interceptor {
public:
    bool preHandle(const Request& request, const Response& response) override {
        return false;
    }

    void postHandle(const Request& request, const Response& response) override {}

    void afterCompletion(const Request& request, const Response& response) override {}
};

InterceptorMacro.h

#pragma once
#include "Reflex.h"
#include "indexInterceptor.h"
#define REFLEX_INPERCEPTOR_DECLARE \
REGISTER_REFLEX(IndexInterceptor)

Cookie.h

#pragma once
#ifndef _COOKIE_
#define _COOKIE_
#include <string>
using namespace std;
class Cookie
{
public:
	Cookie() {}
	Cookie(const string& name, const string& value) :
		_name(name), _value(value) {
		_comment = "";
		_path = "";
		_domain = "";
		_version = "";
		_maxAge = 0;
	}
	string getNameValue() const;
	void setNameValue(const string& name, const string& value);
	void setComment(const string& comment);
	void setPath(const string& path);
	void setDomain(const string& domain);
	void setVersion(const string& version);
	void setMaxAge(const int& maxAge);
	string getComment() const;
	string getPath() const;
	string getDomain() const;
	string getVersion() const;
	int getMaxAge() const;
	string toString() const;
private:
	string _name;
	string _value;
	//注释
	string _comment;
	//路径,若要访问的url startwith(path)此cookie携带
	string _path;
	//网站域名
	string _domain;
	string _version;
	//生存时间
	int _maxAge{ 0 };
};

#endif //!_COOKIE_

Cookie.cpp

#include "Cookie.h"

string Cookie::getNameValue() const
{
	return _name + "=" + _value;
}

void Cookie::setNameValue(const string& name, const string& value)
{
	_name = name;
	_value = value;
}

void Cookie::setComment(const string& comment)
{
	_comment = comment;
}

void Cookie::setPath(const string& path)
{
	_path = path;
}

void Cookie::setDomain(const string& domain)
{
	_domain = domain;
}

void Cookie::setVersion(const string& version)
{
	_version = version;
}

void Cookie::setMaxAge(const int& maxAge)
{
	_maxAge = maxAge;
}

string Cookie::getComment() const
{
	return _comment;
}

string Cookie::getPath() const
{
	return _path;
}

string Cookie::getDomain() const
{
	return _domain;
}

string Cookie::getVersion() const
{
	return _version;
}

int Cookie::getMaxAge() const
{
	return _maxAge;
}

string Cookie::toString() const
{
	string res = getNameValue();
	if (_comment != "") res += ";comment=" + _comment;
	if (_path != "") res += ";Path=" + _path;
	if (_domain != "") res += ";Domain=" + _domain;
	if (_version != "") res += ";Version=" + _version;
	res += ";Max-Age=" + _maxAge;
	return res;
}

CController.h

#pragma once
#ifndef _CCONTROLLER_
#define _CCONTROLLER_
#include "Reflex.h"
using namespace myUtil;
class CController : public RObject
{
};
#endif //!_CCONTROLLER_

indexController.h

#pragma once
#include "CController.h"
#include "Net.h"
#include "Reflex.h"
using namespace myUtil;
class indexController : public CController
{
public:
	indexController() {}
	~indexController() {}
	string index(const Request& req, Response* resp);
	string test(const Request& req, Response* resp);
};

indexController.cpp

#include "indexController.h"
#include <fstream>
using namespace std;

string indexController::index(const Request& req, Response* resp)
{
    resp->setResponseStatus("HTTP", 1, 1, 200, "OK");
    resp->setResponseHead("Content-Type", "text/html,charset=UTF-8");
    return "index.html";
}

string indexController::test(const Request& req, Response* resp)
{
    resp->setResponseStatus("HTTP", 1, 1, 200, "OK");
    resp->setResponseHead("Content-Type", "text/html,charset=UTF-8");
    Cookie cookie("test", "test");
    cookie.setDomain("localhost");
    cookie.setMaxAge(10);
    cookie.setPath("/test");
    resp->setCookie(cookie);
    return "test.html";
}

ControllerMacro.h

#pragma once
#include "indexController.h"
#define REFLEX_DECLARE \
REGISTER_REFLEX(indexController)\
REGISTER_REFLEX_METHOD_ARGS(indexController, index, string, Request&, Response*)\
REGISTER_REFLEX_METHOD_ARGS(indexController, test, string, Request&, Response*)

Net.h

#pragma once
#ifndef _NET_
#define _NET_

#include <string>
#include <wtypes.h>
#include <unordered_map>
#include "Util.h"
#include "Cookie.h"
using namespace std;

NAME_SPACE_START(myUtil)

#define BLACK "\r\n"
#define SPACE " "

class Net {
public:
	virtual string toString() = 0;
	virtual vector<Cookie> getCookie() const = 0;
	virtual void setCookie(const Cookie& cookie) = 0;
	Net() {}
protected:
	vector<Cookie> _cookie;
};

struct RequestStatus
{
	string RMethod;
	string Url;
	string ProName;
	short verHigh;
	short verLow;
};

struct ResponseStatus
{
	string ProName;
	short verHigh;
	short verLow;
	short status;
	string statusWord;
};

//请求
class Request : public Net {
public:
	Request();
	Request(const string& sourceStr);
	void setRequestStatus(const string& method = "GET", const string& url = "/", const string& _proName = "HTTP", const short& _verHigh = 1, const short& _verLow = 1);
	void setRequestHead(const string& headKey, const string& headValue);
	void setRequestContent(const string& content);

	RequestStatus getRequestStatus() const;
	string getRequestContent(const string& headKey) const;

	vector<Cookie> getCookie() const override;
	void setCookie(const Cookie& cookie) override;

	string toString() override;
	~Request() {}
private:
	RequestStatus _status;
	unordered_map<string, string> _RequestHead;
	string _RequestContent{ "" };
};

//响应
//结构 状态行, 响应头部, 空行, 响应正文
class Response : public Net {
public:
	Response();
	void setResponseStatus(const string& _proName = "HTTP", const short& _verHigh = 1, const short& _verLow = 1, const short& status = 200, const string& word = "");
	void setResponseHead(const string& headKey, const string& headValue);
	void setResponseContent(const string& content);

	ResponseStatus getResponseStatus() const;
	string getResponseHeadByKey(const string& headKey) const;

	vector<Cookie> getCookie() const override;
	void setCookie(const Cookie& cookie) override;

	string toString() override;
	~Response();
private:
	ResponseStatus _status;
	unordered_map<string, string> _ResponseHead;
	string _ResponseContent{ "" };
};

class Analyse {
public:
	static vector<string> getVectorBySplit(const string& source, const char& ch);
	static unordered_map<string, string> getMapBySplit(const string& source, const char& ch1,const char& ch2);
	static string makeVectorByChar(const vector<string>& v, const char& ch);
	static string makeMapByChars(const unordered_map<string, string>& m, const char& ch1, const char& ch2);
};


NAME_SPACE_END()
#endif //!_NET_

Net.cpp

#include "Net.h"
NAME_SPACE_START(myUtil)

Response::Response()
{
	_status.ProName = "HTTP";
	_status.verHigh = 1;
	_status.verLow = 1;
	_status.status = 200;
	_status.statusWord = "OK";
}

void Response::setResponseStatus(const string& _proName, const short& _verHigh, const short& _verLow, const short& status, const string& word)
{
	_status.ProName = _proName;
	_status.verHigh = _verHigh;
	_status.verLow = _verLow;
	_status.status = status;
	_status.statusWord = word;
}

void Response::setResponseHead(const string& headKey, const string& headValue)
{
	_ResponseHead.insert(pair<string, string>(headKey, headValue));
}

void Response::setResponseContent(const string& content)
{
	_ResponseContent = content;
}

ResponseStatus Response::getResponseStatus() const
{
	return _status;
}

string Response::getResponseHeadByKey(const string& headKey) const
{
	auto it = _ResponseHead.find(headKey);
	if (it == _ResponseHead.end()) return "";
	return (*it).second;
}

vector<Cookie> Response::getCookie() const
{
	return _cookie;
}

void Response::setCookie(const Cookie& cookie)
{
	_cookie.push_back(cookie);
}

string Response::toString()
{
	string res = "";
	res += _status.ProName + "/" + to_string(_status.verHigh) + "." + to_string(_status.verLow)
		+ SPACE + to_string(_status.status) + SPACE + _status.statusWord + BLACK;
	for (auto it = _ResponseHead.begin(); it != _ResponseHead.end(); it++) {
		res += (*it).first + ":" + SPACE + (*it).second + BLACK;
	}
	res += BLACK;
	res += _ResponseContent;
	return res;
}

Response::~Response()
{
}

Request::Request(const string& sourceStr)
{
	int i = 0;
	vector<string> reqGroup = Analyse::getVectorBySplit(sourceStr, '\n');
	//解析状态行
	vector<string> statuses = Analyse::getVectorBySplit(reqGroup[0], ' ');
	_status.RMethod = statuses.at(0);
	_status.Url = statuses.at(1);
	statuses.at(2).pop_back();
	vector<string> verInfo = Analyse::getVectorBySplit(statuses.at(2), '/');
	_status.ProName = verInfo.at(0);
	_status.verHigh = Analyse::getVectorBySplit(verInfo.at(1), '.').at(0).at(0) - '0';
	_status.verLow = Analyse::getVectorBySplit(verInfo.at(1), '.').at(1).at(0) - '0';
	//解析请求头
	for (i = 1; i < reqGroup.size(); i++) {
		if (reqGroup[i] == "\r")break;
		reqGroup[i].pop_back();
		vector<string> temp = Analyse::getVectorBySplit(reqGroup[i], ':');
		_RequestHead.insert(pair<string, string>(temp.at(0), temp.at(1)));
	}
	i++;
	for (i; i < reqGroup.size(); i++) {
		_RequestContent += reqGroup.at(i) + "\n";
	}
}

void Request::setRequestStatus(const string& method, const string& url, const string& _proName, const short& _verHigh, const short& _verLow)
{
	_status.RMethod = method;
	_status.Url = url;
	_status.ProName = _proName;
	_status.verHigh = _verHigh;
	_status.verLow = _verLow;
}

void Request::setRequestHead(const string& headKey, const string& headValue)
{
	_RequestHead.insert(pair<string, string>(headKey, headValue));
}

void Request::setRequestContent(const string& content)
{
	_RequestContent = content;
}

RequestStatus Request::getRequestStatus() const
{
	return _status;
}

string Request::getRequestContent(const string& headKey) const
{
	return _RequestContent;
}

string Request::toString()
{
	string res = "";
	res += _status.RMethod + SPACE + _status.Url + SPACE + _status.ProName + "/"
		+ to_string(_status.verHigh) + "." + to_string(_status.verLow) + BLACK;
	for (auto it = _RequestHead.begin(); it != _RequestHead.end(); it++) {
		res += (*it).first + ":" + SPACE + (*it).second + BLACK;
	}
	res += BLACK;
	res += _RequestContent;
	return res;
}

vector<Cookie> Request::getCookie() const
{
	return _cookie;
}

void Request::setCookie(const Cookie& cookie)
{
	_cookie.push_back(cookie);
}

vector<string> Analyse::getVectorBySplit(const string& source, const char& ch)
{
	vector<string> res;
	string temp = "";
	for (int i = 0; i < source.size(); i++) {
		if (source[i] == ch) {
			res.push_back(temp);
			temp = "";
		}
		else {
			char ch = source[i];
			temp.push_back(ch);
		}
	}
	if (temp != "") res.push_back(temp);
	return res;
}

unordered_map<string, string> Analyse::getMapBySplit(const string& source, const char& ch1, const char& ch2)
{
	unordered_map<string, string> res;
	vector<string> temp = getVectorBySplit(source, ch1);
	for (string str : temp) {
		vector<string> t = getVectorBySplit(str, ch2);
		if (t.size() != 2) continue;
		res.insert(pair<string, string>(t.at(0), t.at(1)));
	}
	return res;
}

string Analyse::makeVectorByChar(const vector<string>& v, const char& ch)
{
	string res = "";
	for (auto str : v) {
		res += str + ch;
	}
	res.pop_back();
	return res;
}

string Analyse::makeMapByChars(const unordered_map<string, string>& m, const char& ch1, const char& ch2)
{
	string res = "";
	for (auto it = m.begin(); it != m.end(); it++) {
		res += it->first + ch2 + it->second + ch1;
	}
	res.pop_back();
	return res;
}
NAME_SPACE_END()

config.ini

[staticResource]
favicon_path=./ico/favicon.ico

使用方式如下

通过setRoute设置路由规则,类似于springboot中的注释部分
通过setInterceptor设置拦截器规则,如果没有设置的话,会默认找基类
以上两个设置之后还要再两个macro文件中设置宏展开,否则反射找不到对应的类,关于反射如何使用请看这个
https://blog.csdn.net/weixin_43891802/article/details/129411364

#include <iostream>
#include <string>
#include "ControllerMacro.h"
#include "InterceptorMacro.h"
#include "Server.h"
using namespace std;
using namespace myUtil;

REFLEX_DECLARE
REFLEX_INPERCEPTOR_DECLARE

int main() {
    Server server("127.0.0.1", 8080);
    server.setRoute("/", "indexController", "index");
    server.setRoute("/test", "indexController", "test");
    //server.setInterceptor("/test", "IndexInterceptor");
    server.listen(2);
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/1721.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java怎么实现几十万条数据插入(30万条数据插入MySQL仅需13秒)

本文主要讲述通过MyBatis、JDBC等做大数据量数据插入的案例和结果。 30万条数据插入插入数据库验证实体类、mapper和配置文件定义User实体mapper接口mapper.xml文件jdbc.propertiessqlMapConfig.xml不分批次直接梭哈循环逐条插入MyBatis实现插入30万条数据JDBC实现插入30万条数…

第十九天 Maven总结

目录 Maven 1. 前言 2. 概述 2.1 介绍 2.2 安装 3. IDEA集成Maven 3.1 集成Maven环境 3.2 创建Maven项目 3.3 Maven坐标详解 3.4 导入maven项目 4. 依赖管理 4.1 依赖配置 4.2 依赖传递 4.3 依赖范围 4.4 生命周期 4.5 插件 Maven 1. 前言 1). 什么是Maven? …

Linux实操之服务管理

文章目录一、服务(service)管理介绍:service管理指令查看服务名服务的运行级别(runlevel):CentOS7后运行级别说明chkconfig指令介绍一、服务(service)管理介绍: 服务(service)本质就是进程&#xff0c;但是是运行在后台的&#xff0c;通常都会监听某个端口&#xff0c;等待其它…

原力计划来了【协作共赢 成就未来】

catalogue&#x1f31f; 写在前面&#x1f31f; 新星计划持续上新&#x1f31f; 原力计划方向&#x1f31f; 原力计划拥抱优质&#x1f31f; AIGC&#x1f31f; 参加新星计划还是原力计划&#x1f31f; 创作成就未来&#x1f31f; 写在最后&#x1f31f; 写在前面 哈喽&#x…

依赖注入~

依赖注入之setter注入&#xff1a; 依赖注入是IOC具体的一种实现方式&#xff0c; 这是针对资源获取的方式角度来说的&#xff0c;之前我们是被动接受&#xff0c;现在IOC具体的实现叫做依赖注入&#xff0c;从代码的角度来说&#xff0c;原来创建对象的时候需要new&#xff0…

Phoenix基础命令_视图映射和表映射_数字存储问题---大数据之Hbase工作笔记0036

然后我们再来看看,用Phoenix来操作hbase,的基本用法 具体的其他的命令在官网都能找到,这里就说几个 https://phoenix.apache.org/language/index.html 首先是创建表,这里注意,默认表名给弄成大写的 这里的varchar对应的其实就是hbase中的string 然后这里的id表示行的rowkey 可…

chatgpt3.5和chatgpt4的区别

ChatGPT4是基于GPT-3模型的一个实例&#xff0c;但ChatGPT4已经进行了进一步的改进和优化。GPT-3&#xff08;第三代生成式预训练模型&#xff09;是OpenAl开发的一个大型语言模型&#xff0c;它在很多自然语言处理任务中表现出色。ChatGPT4继承了GPT-3的基本架构和能力&#x…

复旦微ZYNQ7020全国产替代方案设计

现在国产化进度赶人&#xff0c;进口的芯片只做了个功能验证&#xff0c;马上就要换上国产的。国内现在已经做出来zynq的只有复旦微一家&#xff0c;已经在研制的有上海安路&#xff0c;还有成都华微&#xff08;不排除深圳国威也在做&#xff0c;毕竟这个市场潜力很大&#xf…

如何在Unity中实现AStar寻路算法及地图编辑器

文章目录AStar算法简介实现Node节点节点间的估价算法核心邻节点的搜索方式地图编辑器简介实现绘制地图网格障碍/可行走区域地图数据存储AStar算法 简介 Unity中提供了NavMesh导航寻路的AI功能&#xff0c;如果项目不涉及服务端它应该能满足大部分需求&#xff0c;但如果涉及服…

树莓派(3B):启动流程,系统初始化配置,引脚图图示说明

目录 一&#xff0c;树莓派刷机及串口方式登陆 ① 准备工具 ② 操作步骤 二&#xff0c;配置树莓派接入网络 ① 树莓派入网 ② 固定树莓派的ip地址 三&#xff0c;网络SSH方式登陆树莓派 ① 打开树莓派SSH功能 ② 登陆SSH 四&#xff0c;用国内的源更新vim 五&…

48天C++笔试强训 001

作者&#xff1a;小萌新 专栏&#xff1a;笔试强训 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;讲解48天笔试强训第一天的题目 笔试强训 day1选择题12345678910编程题12选择题 1 以下for循环的执行次数是&#xff08;&#xff…

手把手教你基于HTML、CSS搭建我的相册(上)

The sand accumulates to form a pagoda写在前面HTML是什么&#xff1f;CSS是什么&#xff1f;demo搭建写在最后写在前面 其实有过一些粉丝咨询前端该从什么开始学&#xff0c;那当然是我们的前端基础三件套开始学起&#xff0c;HTML、CSS、javaScript&#xff0c;前端的大部分…

字符函数和字符串函数【下篇】

文章目录&#x1f396;️1.函数介绍&#x1f4ec;1.8. strstr&#x1f4ec;1.9. strtok&#x1f4ec;1.10. strerror&#x1f4ec;1.11. memcpy&#x1f4ec;1.12. memmove&#x1f4ec;1.13. memcmp&#x1f4ec;1.14. memset&#x1f396;️1.函数介绍 &#x1f4ec;1.8. st…

Linux - 进程控制(进程等待)

进程等待必要性之前讲过&#xff0c;子进程退出&#xff0c;父进程如果不管不顾&#xff0c;就可能造成‘僵尸进程’的问题&#xff0c;进而造成内存泄漏。另外&#xff0c;进程一旦变成僵尸状态&#xff0c;那就刀枪不入&#xff0c;“杀人不眨眼”的kill -9 也无能为力&#…

基于java下Springboot框架实现旅游管理平台系统

基于java下Springboot框架实现旅游管理平台系统开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven…

自动驾驶自主避障概况

文章目录前言1. 自主避障在自动驾驶系统架构中的位置2. 自主避障算法分类2.1 人工势场法&#xff08;APF&#xff09;2.1.1引力势场的构建2.1.2斥力势场的构建2.1.3人工势场法的改进2.2 TEB&#xff08;Timed-Eastic-Band, 定时弹性带&#xff09;2.3 栅格法2.4 向量场直方图(V…

基于鲸鱼算法的极限学习机(ELM)分类算法-附代码

基于鲸鱼算法的极限学习机(ELM)分类算法 文章目录基于鲸鱼算法的极限学习机(ELM)分类算法1.极限学习机原理概述2.ELM学习算法3.分类问题4.基于鲸鱼算法优化的ELM5.测试结果6.参考文献7.Matlab代码摘要&#xff1a;本文利用鲸鱼算法对极限学习机进行优化&#xff0c;并用于分类问…

C++继承

文章目录继承的概念和定义继承的概念继承定义继承定义格式继承基类成员访问方式的变化基类和派生类对象赋值转换继承中的作用域派生类的默认成员函数继承与友元继承与静态成员复杂的菱形继承及菱形虚拟继承菱形虚拟继承菱形虚拟继承原理菱形虚拟继承中虚指针应用继承的总结和反…

【C语言】字符串函数和内存函数

前言&#x1f338;在我们编写C程序时&#xff0c;除了使用自定义函数&#xff0c;往往还会使用一些库函数&#xff0c;例如标准输入输出函数printf&#xff0c;scanf&#xff0c;字符串函数strlen&#xff0c;内存函数memset等等&#xff0c;使用这些系统自带的库函数可以轻松地…

MongoDB【部署 01】mongodb最新版本6.0.5安装部署配置使用及mongodb-shell1.8.0安装使用(云盘分享安装文件)

云盘分享文件&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/11sbj1QgogYHPM4udwoB1rA 提取码&#xff1a;l2wz 1.mongodb简单介绍 MongoDB的 官网 内容还是挺丰富的。 是由 C语言编写的&#xff0c;是一个基于分布式文件存储的开源数据库系统。在高负载的情况下&…
最新文章