当前位置: 首页 > 工具软件 > gStore > 使用案例 >

gstore源码解析(二):SOCKET网络服务源码解析

朱保赫
2023-12-01

gstore源码解析(二):SOCKET网络服务源码解析


​ 上一章我们介绍了基于boost实现的gstore http网络服务,本章将介绍基于TCP协议的socket网络服务。

1.1 简介

​ gserver模块实现了一个基于TCP协议的socket网络服务,支持socket API双向通信。本章将从服务参数解析、运行机制、请求解析三个方面来展开。

1.2 服务参数解析

​ gserver提供了丰富的操作参数,可以通过不同参数来进行一系列的操作,如启动、停止、重启服务、配置端口、查看端口等。实现的片段代码如下:

通过-h--help参数查看帮助信息

else if (mode == "-h" || mode == "--help") {
    cout << endl;
    cout << "gStore Server (gServer)" << endl;
    cout << endl;
    cout << "Usage:\tbin/gserver [option]" << endl;
    cout << endl;
    cout << "Options:" << endl;
    cout << "\t-h,--help\t\tDisplay this message." << endl;
    cout << "\t-s,--start\t\tStart gServer." << endl;
    cout << "\t-t,--stop\t\tStop gServer." << endl;
    cout << "\t-r,--restart\t\tRestart gServer." << endl;
    cout << "\t-p,--port [PORT=" << Socket::DEFAULT_CONNECT_PORT << "]\tChange connection port configuration, takes effect after restart if gServer running." << endl;
    cout << "\t-P,--printport\t\tDisplay current connection port configuration." << endl;
    cout << "\t-d,--debug\t\tStart gServer in debug mode (keep gServer in the foreground)." << endl;
    cout << "\t-k,--kill\t\tKill existing gServer process(es), ONLY use when out of normal procedures." << endl;
    cout << endl;
    return 0;
}

通过-p--port参数设置监听端口,如果不进行设置,默认监听端口为9000(Socket::DEFAULT_CONNECT_PORT)

if (mode == "-p" || mode == "--port") {
    // 初始化端口为默认端口9000
    unsigned short port = Socket::DEFAULT_CONNECT_PORT;
    if (argc == 3) {
        if (!Util::isValidPort(string(argv[2]))) {
            cerr << "Invalid port: " << argv[2] << endl;
            return -1;
        }
        else {
            stringstream ss(argv[2]);
            ss >> port;
        }
    }
    // 如果socket服务已启动,修改成功后需要重启后新端口才会生效
    if (!isOnlyProcess(argv[0])) {
        ofstream out(Util::gserver_port_swap.c_str());
        if (!out) {
            cerr << "Failed to change port!" << endl;
            return -1;
        }
        out << port;
        out.close();
        cout << "Port will be changed to " << port << " after the current server stops or restarts." << endl;
        return 0;
    }
    ofstream out(Util::gserver_port_file.c_str());
    if (!out) {
        cerr << "Failed to change port!" << endl;
        return -1;
    }
    out << port;
    out.close();
    cout << "Port changed to " << port << '.' << endl;
    return 0;
}

通过-s--start参数启动服务

else if (mode == "-s" || mode == "--start") {
    // 判断服务是否已存在
    if (!isOnlyProcess(argv[0])) {
        cerr << "gServer already running!" << endl;
        return -1;
    }
    // 启动服务器,false表示非调试模式,在后面将介绍·
    if (startServer(false)) {
        sleep(1);
        if (isOnlyProcess(argv[0])) {
            cerr << "Server stopped unexpectedly. Check for port conflicts!" << endl;
            return -1;
        }
        return 0;
    }
    else {
        return -1;
    }
}

// startServer函数部分关键代码
bool startServer(bool _debug) {
    // 从配置文件中读取配置的端口号,如果没有则为默认端口Socket::DEFAULT_CONNECT_PORT
	unsigned short port = Socket::DEFAULT_CONNECT_PORT;
	ifstream in(Util::gserver_port_file.c_str());
	if (!in) {
		ofstream out(Util::gserver_port_file.c_str());
		if (out) {
			out << port;
			out.close();
			chmod(Util::gserver_port_file.c_str(), 0644);
		}
	}
	....
    // fock子进程,通过子进程启动服务,当子进程因某些异常被中断后,主进程将自动创建新的子进程
	pid_t fpid = fork();
	if (fpid == 0) {
		if (!Util::dir_exist("logs")) {
			Util::create_dir("logs");
		}
		freopen(Util::gserver_log.c_str(), "a", stdout);
		freopen(Util::gserver_log.c_str(), "a", stderr);
		int status;
		while (true) {
			fpid = fork();
			if (fpid == 0) {
                // 初始化服务
				Server server(port);
				if (!server.createConnection()) {
					cerr << Util::getTimeString() << "Failed to create connection at port " << port << '.' << endl;
					return false;
				}
				cout << Util::getTimeString() << "Server started at port " << port << '.' << endl;
				// 启动监听,开始接收客户端的请求
                server.listen();
				server.deleteConnection();
				exit(0);
				return true;
			}
            ......
		}
	}
    .....
}

通过-t--stop命令停止服务

else if (mode == "-t" || mode == "--stop") {
    if (isOnlyProcess(argv[0])) {
        cerr << "gServer not running!" << endl;
        return -1;
    }
    // 通过发送socket api请求(op=stop)到服务端,由服务端进行停服处理
    if (stopServer()) {
        return 0;
    }
    else {
        return -1;
    }
}

通过-r--restart命令重启服务

else if (mode == "-r" || mode == "--restart") {
    // 判断服务是否在运行
    if (isOnlyProcess(argv[0])) {
        cerr << "gServer not running!" << endl;
        return -1;
    }
    // 停止服务
    if (!stopServer()) {
        return -1;
    }
    // 启动服务
    if (startServer(false)) {
        sleep(1);
        if (isOnlyProcess(argv[0])) {
            cerr << "Server stopped unexpectedly. Check for port conflicts!" << endl;
            return -1;
        }
        return 0;
    }
    ......
}

通过-p--printport命令查看当前配置的端口

else if (mode == "-P" || mode == "--printport") {
    unsigned short port = Socket::DEFAULT_CONNECT_PORT;
    ifstream in(Util::gserver_port_file.c_str());
    if (in) {
        in >> port;
        in.close();
    }
    cout << "Current connection port is " << port << '.' << endl;
    unsigned short portSwap = 0;
    ifstream inSwap(Util::gserver_port_swap.c_str());
    if (inSwap) {
        inSwap >> portSwap;
        inSwap.close();
    }
    if (portSwap != 0) {
        cout << "Connection port to be changed to " << portSwap << '.' << endl;
    }
    return 0;
}

通过-k--kill命令强制停止服务,当通过-t无法正常停服时,可使用改命令强制停止

else if (mode == "-k" || mode == "--kill") {
    if (isOnlyProcess(argv[0])) {
        cerr << "No process to kill!" << endl;
        return -1;
    }
    execl("/usr/bin/killall", "killall", Util::getExactPath(argv[0]).c_str(), NULL);
    return 0;
}

1.3 运行机制

​ 在前面介绍中,通过-s--start参数启动服务后,将在startServer函数中fork一个子进程,并通过子进程完成服务的初始化和监听,等待客户端的连接请求。部分关键代码解析如下:

服务初始化并绑定端口

// 源码路径:Server/Server.cpp Server/Socket.cpp
bool Server::createConnection(){
    bool flag;
    // 调用Socket::create创建socket
    flag = this->socket.create();
    if (!flag){
        cerr << Util::getTimeString() << "Cannot create socket.@Server::createConnection" << endl;
        return false;
    }
    // 调用Socket::bind绑定端口
    flag = this->socket.bind(this->connectionPort);
    if (!flag)
    {
        cerr << Util::getTimeString() << "Cannot bind to port " << this->connectionPort << ". @Server::createConnection" << endl;
        return false;
    }
    // 开启请求监听
    flag = this->socket.listen();
    if (!flag)
    {
        cerr << Util::getTimeString() << "Cannot listen to port" << this->connectionPort << ". @Server::createConnection" << endl;
        return false;
    }
    return true;
}

监听连接,当有新的请求进来后,会创建一个子线程去处理请求,函数的代码片段如下:

void Server::listen(){
	this->init();
	Socket soc[this->connectionMaxNum];
	int i = 0;
	Socket new_server_socket;
	while (true)
	{
		/**
		* @brief Receive the stopServer signal.
		*/
		signal(SIGTERM, Server::stop_sigterm_handler);
		cout << Util::getTimeString() << "Wait for connection..." << endl;
        // 等待连接请求
		this->socket.accept(new_server_socket);
		cout << Util::getTimeString() << "Accept a new socket connection." << endl;
		/**
		* @brief Create a thread for a client socket.
		*/
		memcpy(&soc[i], &new_server_socket, sizeof(Socket));
		sockThread* tid = new sockThread(soc[i++]);
		tid->server = this;
		tid->start();
	}
}
// 子线程的关键代码段如下
void sockThread::run()
{
	cout << Util::getTimeString() << "Thread:" << tid << " run\n";
	server->handler(socket);
}
// 通过thread::detach()分离主线程
void sockThread::start()
{
	TD = std::thread(&sockThread::run, this);
	TD.detach();
}

1.4 请求解析

​ 在运行机制中介绍了通过创建子线程来处理每个请求,在sockThread::run()函数中,请求最终将调用Server::handler(Socket& _socket)方法进行统一处理并返回处理结果,部分代码片段如下:

void
Server::handler(Socket& _socket) {
	int repeated_num = 0;
	while (true) {
        // 10次尝试仍未成功将关闭该次请求
		if (repeated_num > 10)
			break;
		/**
		* @brief Receive the command message from the client.
		*/
		std::string recv_cmd;
        // 接收请求的数据
		bool recv_return = _socket.recv(recv_cmd);
		if (!recv_return)
		{
			cerr << Util::getTimeString() << "Receive command from client error.@Server::listen" << endl;
			repeated_num++;
			continue;
		}
		cout << Util::getTimeString() << "Received msg: " << recv_cmd << endl;
        ......
    }
}

在正确接收到客户端请求的数据后,将对数据进行解析并调用对应的方法进行处理,socket api请求的数据格式为JSON字符串,格式如下:

{"op":"[op_type]","[param1]":"[value1]","[param2]":"[value2]"……}

op为指令参数,[paramx]为不同接口要求的参数,op参数对应的类型如下:

// Server/Operation.h
enum CommandType {
	CMD_OTHER, /**< enum value other. */
	CMD_TEST, /**< enum value test. */
	CMD_LOGIN, /**< enum value login. */
	CMD_BUILD, /**< enum value build. */
	CMD_LOAD, /**< enum value load. */
	CMD_UNLOAD, /**< enum value unload. */
	CMD_QUERY, /**< enum value query. */
	CMD_SHOW, /**< enum value show. */
	CMD_STOP, /**< enum value stop. */
	CMD_DROP, /**< enum value drop. */
	CMD_CLOSE /**< enum value close. */
};

// Server/Server.cpp
bool Server::parser(std::string _raw_cmd, Operation& _ret_oprt) {
	......
	if (cmd == "test") { //心跳检测
		_ret_oprt.setCommand(CMD_TEST);
	}
	if (cmd == "login") {//登录
		_ret_oprt.setCommand(CMD_LOGIN);
        ......
	}
	else if (cmd == "build") {//创建
		_ret_oprt.setCommand(CMD_BUILD);
		......
	}
	else if (cmd == "load") {//加载
		_ret_oprt.setCommand(CMD_LOAD);
		......
	}
	else if (cmd == "unload") {//卸载
		_ret_oprt.setCommand(CMD_UNLOAD);
		......
	}
	else if (cmd == "query") {//查询
		_ret_oprt.setCommand(CMD_QUERY);
		......
	}
	else if (cmd == "show") {//查看库
		_ret_oprt.setCommand(CMD_SHOW);
		......
	}
	else if (cmd == "stop") {//停止服务
		_ret_oprt.setCommand(CMD_STOP);
		......
	}
	else if (cmd == "close") {//关闭连接
		_ret_oprt.setCommand(CMD_CLOSE);
		......
	}
	else if (cmd == "drop") {//删除库
		_ret_oprt.setCommand(CMD_DROP);
		......
	}
	......
}

通过op参数来识别请求的接口,并调用对应的接口函数进行处理,部分代码片段如下:

void
Server::handler(Socket& _socket)
{
	int repeated_num = 0;
	while (true)
	{
        ......
		/**
		* @brief Execute the specific command function.
		*/
		std::string ret_msg;
		CommandType cmd_type = operation.getCommand();
		bool _close = false;
		switch (cmd_type)
		{
		case CMD_TEST: //心跳检测
		{
			ret_msg = "OK";
			break;
		}
		case CMD_LOGIN://登录
		{
			std::string username = operation.getParameter("username");
			std::string password = operation.getParameter("password");
			this->login(username, password, _socket);
			break;
		}
		case CMD_LOAD://加载库
		{
			std::string db_name = operation.getParameter("db_name");
			this->load(db_name, _socket);
			break;
		}
		case CMD_UNLOAD://卸载库
		{
			std::string db_name = operation.getParameter("db_name");
			this->unload(db_name, _socket);
			break;
		}
		case CMD_BUILD://创建库
		{
			std::string db_name = operation.getParameter("db_name");
			std::string db_path = operation.getParameter("db_path");
			this->build(db_name, db_path, _socket);
			break;
		}
		case CMD_DROP://删除库
		{
			std::string db_name = operation.getParameter("db_name");
			this->drop(db_name, _socket);
			break;
		}
		case CMD_QUERY://查询
		{
			std::string db_name = operation.getParameter("db_name");
			std::string sparql = operation.getParameter("sparql");

			pthread_t timer = Server::start_timer();
			if (timer == 0) {
				cerr << Util::getTimeString() << "Failed to start timer." << endl;
			}
			this->query(db_name, sparql, _socket);
			if (timer != 0 && !Server::stop_timer(timer)) {
				cerr << Util::getTimeString() << "Failed to stop timer." << endl;
			}
			break;
		}
		case CMD_SHOW://查看库
		{
			this->show(_socket);
			break;
		}
		case CMD_STOP://停止服务
		{
			this->stopServer(_socket);
			_stop = true;
			_close = true;
			break;
		}
		case CMD_CLOSE://关闭连接
		{
			this->closeConnection(_socket);
			_close = true;
			break;
		}
		......
	}
	......
}

​ 各接口函数的实现逻辑与ghttp模块的接口函数基本相同,这里将不再重复进行介绍,各接口的使用说明可查阅文章#gStore-weekly | gStore最新版本0.9.1之gServer详解(上)#gStore-weekly | gStore最新版本0.9.1之gServer详解(下)

1.6 小结

​ 本章节介绍了socket网络服务gserver模块,如何实现服务参数解析、服务运行机制以及请求的处理逻辑,建议在阅读的同时结合源码Main/gserver.cpp一起分析,会更容易理解。下一章将开始介绍gstore的安全机制系列源码。gstore源码解析(二):SOCKET网络服务源码解析


​ 上一章我们介绍了基于boost实现的gstore http网络服务,本章将介绍基于TCP协议的socket网络服务。

1.1 简介

​ gserver模块实现了一个基于TCP协议的socket网络服务,支持socket API双向通信。本章将从服务参数解析、运行机制、请求解析三个方面来展开。

1.2 服务参数解析

​ gserver提供了丰富的操作参数,可以通过不同参数来进行一系列的操作,如启动、停止、重启服务、配置端口、查看端口等。实现的片段代码如下:

通过-h--help参数查看帮助信息

else if (mode == "-h" || mode == "--help") {
    cout << endl;
    cout << "gStore Server (gServer)" << endl;
    cout << endl;
    cout << "Usage:\tbin/gserver [option]" << endl;
    cout << endl;
    cout << "Options:" << endl;
    cout << "\t-h,--help\t\tDisplay this message." << endl;
    cout << "\t-s,--start\t\tStart gServer." << endl;
    cout << "\t-t,--stop\t\tStop gServer." << endl;
    cout << "\t-r,--restart\t\tRestart gServer." << endl;
    cout << "\t-p,--port [PORT=" << Socket::DEFAULT_CONNECT_PORT << "]\tChange connection port configuration, takes effect after restart if gServer running." << endl;
    cout << "\t-P,--printport\t\tDisplay current connection port configuration." << endl;
    cout << "\t-d,--debug\t\tStart gServer in debug mode (keep gServer in the foreground)." << endl;
    cout << "\t-k,--kill\t\tKill existing gServer process(es), ONLY use when out of normal procedures." << endl;
    cout << endl;
    return 0;
}

通过-p--port参数设置监听端口,如果不进行设置,默认监听端口为9000(Socket::DEFAULT_CONNECT_PORT)

if (mode == "-p" || mode == "--port") {
    // 初始化端口为默认端口9000
    unsigned short port = Socket::DEFAULT_CONNECT_PORT;
    if (argc == 3) {
        if (!Util::isValidPort(string(argv[2]))) {
            cerr << "Invalid port: " << argv[2] << endl;
            return -1;
        }
        else {
            stringstream ss(argv[2]);
            ss >> port;
        }
    }
    // 如果socket服务已启动,修改成功后需要重启后新端口才会生效
    if (!isOnlyProcess(argv[0])) {
        ofstream out(Util::gserver_port_swap.c_str());
        if (!out) {
            cerr << "Failed to change port!" << endl;
            return -1;
        }
        out << port;
        out.close();
        cout << "Port will be changed to " << port << " after the current server stops or restarts." << endl;
        return 0;
    }
    ofstream out(Util::gserver_port_file.c_str());
    if (!out) {
        cerr << "Failed to change port!" << endl;
        return -1;
    }
    out << port;
    out.close();
    cout << "Port changed to " << port << '.' << endl;
    return 0;
}

通过-s--start参数启动服务

else if (mode == "-s" || mode == "--start") {
    // 判断服务是否已存在
    if (!isOnlyProcess(argv[0])) {
        cerr << "gServer already running!" << endl;
        return -1;
    }
    // 启动服务器,false表示非调试模式,在后面将介绍·
    if (startServer(false)) {
        sleep(1);
        if (isOnlyProcess(argv[0])) {
            cerr << "Server stopped unexpectedly. Check for port conflicts!" << endl;
            return -1;
        }
        return 0;
    }
    else {
        return -1;
    }
}

// startServer函数部分关键代码
bool startServer(bool _debug) {
    // 从配置文件中读取配置的端口号,如果没有则为默认端口Socket::DEFAULT_CONNECT_PORT
	unsigned short port = Socket::DEFAULT_CONNECT_PORT;
	ifstream in(Util::gserver_port_file.c_str());
	if (!in) {
		ofstream out(Util::gserver_port_file.c_str());
		if (out) {
			out << port;
			out.close();
			chmod(Util::gserver_port_file.c_str(), 0644);
		}
	}
	....
    // fock子进程,通过子进程启动服务,当子进程因某些异常被中断后,主进程将自动创建新的子进程
	pid_t fpid = fork();
	if (fpid == 0) {
		if (!Util::dir_exist("logs")) {
			Util::create_dir("logs");
		}
		freopen(Util::gserver_log.c_str(), "a", stdout);
		freopen(Util::gserver_log.c_str(), "a", stderr);
		int status;
		while (true) {
			fpid = fork();
			if (fpid == 0) {
                // 初始化服务
				Server server(port);
				if (!server.createConnection()) {
					cerr << Util::getTimeString() << "Failed to create connection at port " << port << '.' << endl;
					return false;
				}
				cout << Util::getTimeString() << "Server started at port " << port << '.' << endl;
				// 启动监听,开始接收客户端的请求
                server.listen();
				server.deleteConnection();
				exit(0);
				return true;
			}
            ......
		}
	}
    .....
}

通过-t--stop命令停止服务

else if (mode == "-t" || mode == "--stop") {
    if (isOnlyProcess(argv[0])) {
        cerr << "gServer not running!" << endl;
        return -1;
    }
    // 通过发送socket api请求(op=stop)到服务端,由服务端进行停服处理
    if (stopServer()) {
        return 0;
    }
    else {
        return -1;
    }
}

通过-r--restart命令重启服务

else if (mode == "-r" || mode == "--restart") {
    // 判断服务是否在运行
    if (isOnlyProcess(argv[0])) {
        cerr << "gServer not running!" << endl;
        return -1;
    }
    // 停止服务
    if (!stopServer()) {
        return -1;
    }
    // 启动服务
    if (startServer(false)) {
        sleep(1);
        if (isOnlyProcess(argv[0])) {
            cerr << "Server stopped unexpectedly. Check for port conflicts!" << endl;
            return -1;
        }
        return 0;
    }
    ......
}

通过-p--printport命令查看当前配置的端口

else if (mode == "-P" || mode == "--printport") {
    unsigned short port = Socket::DEFAULT_CONNECT_PORT;
    ifstream in(Util::gserver_port_file.c_str());
    if (in) {
        in >> port;
        in.close();
    }
    cout << "Current connection port is " << port << '.' << endl;
    unsigned short portSwap = 0;
    ifstream inSwap(Util::gserver_port_swap.c_str());
    if (inSwap) {
        inSwap >> portSwap;
        inSwap.close();
    }
    if (portSwap != 0) {
        cout << "Connection port to be changed to " << portSwap << '.' << endl;
    }
    return 0;
}

通过-k--kill命令强制停止服务,当通过-t无法正常停服时,可使用改命令强制停止

else if (mode == "-k" || mode == "--kill") {
    if (isOnlyProcess(argv[0])) {
        cerr << "No process to kill!" << endl;
        return -1;
    }
    execl("/usr/bin/killall", "killall", Util::getExactPath(argv[0]).c_str(), NULL);
    return 0;
}

1.3 运行机制

​ 在前面介绍中,通过-s--start参数启动服务后,将在startServer函数中fork一个子进程,并通过子进程完成服务的初始化和监听,等待客户端的连接请求。部分关键代码解析如下:

服务初始化并绑定端口

// 源码路径:Server/Server.cpp Server/Socket.cpp
bool Server::createConnection(){
    bool flag;
    // 调用Socket::create创建socket
    flag = this->socket.create();
    if (!flag){
        cerr << Util::getTimeString() << "Cannot create socket.@Server::createConnection" << endl;
        return false;
    }
    // 调用Socket::bind绑定端口
    flag = this->socket.bind(this->connectionPort);
    if (!flag)
    {
        cerr << Util::getTimeString() << "Cannot bind to port " << this->connectionPort << ". @Server::createConnection" << endl;
        return false;
    }
    // 开启请求监听
    flag = this->socket.listen();
    if (!flag)
    {
        cerr << Util::getTimeString() << "Cannot listen to port" << this->connectionPort << ". @Server::createConnection" << endl;
        return false;
    }
    return true;
}

监听连接,当有新的请求进来后,会创建一个子线程去处理请求,函数的代码片段如下:

void Server::listen(){
	this->init();
	Socket soc[this->connectionMaxNum];
	int i = 0;
	Socket new_server_socket;
	while (true)
	{
		/**
		* @brief Receive the stopServer signal.
		*/
		signal(SIGTERM, Server::stop_sigterm_handler);
		cout << Util::getTimeString() << "Wait for connection..." << endl;
        // 等待连接请求
		this->socket.accept(new_server_socket);
		cout << Util::getTimeString() << "Accept a new socket connection." << endl;
		/**
		* @brief Create a thread for a client socket.
		*/
		memcpy(&soc[i], &new_server_socket, sizeof(Socket));
		sockThread* tid = new sockThread(soc[i++]);
		tid->server = this;
		tid->start();
	}
}
// 子线程的关键代码段如下
void sockThread::run()
{
	cout << Util::getTimeString() << "Thread:" << tid << " run\n";
	server->handler(socket);
}
// 通过thread::detach()分离主线程
void sockThread::start()
{
	TD = std::thread(&sockThread::run, this);
	TD.detach();
}

1.4 请求解析

​ 在运行机制中介绍了通过创建子线程来处理每个请求,在sockThread::run()函数中,请求最终将调用Server::handler(Socket& _socket)方法进行统一处理并返回处理结果,部分代码片段如下:

void
Server::handler(Socket& _socket) {
	int repeated_num = 0;
	while (true) {
        // 10次尝试仍未成功将关闭该次请求
		if (repeated_num > 10)
			break;
		/**
		* @brief Receive the command message from the client.
		*/
		std::string recv_cmd;
        // 接收请求的数据
		bool recv_return = _socket.recv(recv_cmd);
		if (!recv_return)
		{
			cerr << Util::getTimeString() << "Receive command from client error.@Server::listen" << endl;
			repeated_num++;
			continue;
		}
		cout << Util::getTimeString() << "Received msg: " << recv_cmd << endl;
        ......
    }
}

在正确接收到客户端请求的数据后,将对数据进行解析并调用对应的方法进行处理,socket api请求的数据格式为JSON字符串,格式如下:

{"op":"[op_type]","[param1]":"[value1]","[param2]":"[value2]"……}

op为指令参数,[paramx]为不同接口要求的参数,op参数对应的类型如下:

// Server/Operation.h
enum CommandType {
	CMD_OTHER, /**< enum value other. */
	CMD_TEST, /**< enum value test. */
	CMD_LOGIN, /**< enum value login. */
	CMD_BUILD, /**< enum value build. */
	CMD_LOAD, /**< enum value load. */
	CMD_UNLOAD, /**< enum value unload. */
	CMD_QUERY, /**< enum value query. */
	CMD_SHOW, /**< enum value show. */
	CMD_STOP, /**< enum value stop. */
	CMD_DROP, /**< enum value drop. */
	CMD_CLOSE /**< enum value close. */
};

// Server/Server.cpp
bool Server::parser(std::string _raw_cmd, Operation& _ret_oprt) {
	......
	if (cmd == "test") { //心跳检测
		_ret_oprt.setCommand(CMD_TEST);
	}
	if (cmd == "login") {//登录
		_ret_oprt.setCommand(CMD_LOGIN);
        ......
	}
	else if (cmd == "build") {//创建
		_ret_oprt.setCommand(CMD_BUILD);
		......
	}
	else if (cmd == "load") {//加载
		_ret_oprt.setCommand(CMD_LOAD);
		......
	}
	else if (cmd == "unload") {//卸载
		_ret_oprt.setCommand(CMD_UNLOAD);
		......
	}
	else if (cmd == "query") {//查询
		_ret_oprt.setCommand(CMD_QUERY);
		......
	}
	else if (cmd == "show") {//查看库
		_ret_oprt.setCommand(CMD_SHOW);
		......
	}
	else if (cmd == "stop") {//停止服务
		_ret_oprt.setCommand(CMD_STOP);
		......
	}
	else if (cmd == "close") {//关闭连接
		_ret_oprt.setCommand(CMD_CLOSE);
		......
	}
	else if (cmd == "drop") {//删除库
		_ret_oprt.setCommand(CMD_DROP);
		......
	}
	......
}

通过op参数来识别请求的接口,并调用对应的接口函数进行处理,部分代码片段如下:

void
Server::handler(Socket& _socket)
{
	int repeated_num = 0;
	while (true)
	{
        ......
		/**
		* @brief Execute the specific command function.
		*/
		std::string ret_msg;
		CommandType cmd_type = operation.getCommand();
		bool _close = false;
		switch (cmd_type)
		{
		case CMD_TEST: //心跳检测
		{
			ret_msg = "OK";
			break;
		}
		case CMD_LOGIN://登录
		{
			std::string username = operation.getParameter("username");
			std::string password = operation.getParameter("password");
			this->login(username, password, _socket);
			break;
		}
		case CMD_LOAD://加载库
		{
			std::string db_name = operation.getParameter("db_name");
			this->load(db_name, _socket);
			break;
		}
		case CMD_UNLOAD://卸载库
		{
			std::string db_name = operation.getParameter("db_name");
			this->unload(db_name, _socket);
			break;
		}
		case CMD_BUILD://创建库
		{
			std::string db_name = operation.getParameter("db_name");
			std::string db_path = operation.getParameter("db_path");
			this->build(db_name, db_path, _socket);
			break;
		}
		case CMD_DROP://删除库
		{
			std::string db_name = operation.getParameter("db_name");
			this->drop(db_name, _socket);
			break;
		}
		case CMD_QUERY://查询
		{
			std::string db_name = operation.getParameter("db_name");
			std::string sparql = operation.getParameter("sparql");

			pthread_t timer = Server::start_timer();
			if (timer == 0) {
				cerr << Util::getTimeString() << "Failed to start timer." << endl;
			}
			this->query(db_name, sparql, _socket);
			if (timer != 0 && !Server::stop_timer(timer)) {
				cerr << Util::getTimeString() << "Failed to stop timer." << endl;
			}
			break;
		}
		case CMD_SHOW://查看库
		{
			this->show(_socket);
			break;
		}
		case CMD_STOP://停止服务
		{
			this->stopServer(_socket);
			_stop = true;
			_close = true;
			break;
		}
		case CMD_CLOSE://关闭连接
		{
			this->closeConnection(_socket);
			_close = true;
			break;
		}
		......
	}
	......
}

​ 各接口函数的实现逻辑与ghttp模块的接口函数基本相同,这里将不再重复进行介绍,各接口的使用说明可查阅文章#gStore-weekly | gStore最新版本0.9.1之gServer详解(上)#gStore-weekly | gStore最新版本0.9.1之gServer详解(下)

1.6 小结

​ 本章节介绍了socket网络服务gserver模块,如何实现服务参数解析、服务运行机制以及请求的处理逻辑,建议在阅读的同时结合源码Main/gserver.cpp一起分析,会更容易理解。下一章将开始介绍gstore的安全机制系列源码。

 类似资料: