You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
workflow/src/server/WFServer.h

254 lines
8.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
Copyright (c) 2019 Sogou, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Authors: Xie Han (xiehan@sogou-inc.com)
Wu Jiaxu (wujiaxu@sogou-inc.com)
*/
#ifndef _WFSERVER_H_ // 防止头文件被多次包含
#define _WFSERVER_H_
#include <sys/types.h> // 引入基本数据类型定义
#include <sys/socket.h> // 引入 socket 相关的函数
#include <errno.h> // 引入错误码定义
#include <functional> // 引入函数对象
#include <atomic> // 引入原子操作的支持
#include <mutex> // 引入互斥量支持
#include <condition_variable> // 引入条件变量支持
#include <openssl/ssl.h> // 引入 OpenSSL 以支持 SSL/TLS
#include "EndpointParams.h" // 引入端点参数定义
#include "WFTaskFactory.h" // 引入任务工厂以创建任务
// 定义服务器参数结构体
struct WFServerParams
{
enum TransportType transport_type; // 传输类型TCP, UDP, SSL等
size_t max_connections; // 最大并发连接数
int peer_response_timeout; // 每次读取或写入操作的超时
int receive_timeout; // 接收整个消息的超时
int keep_alive_timeout; // 连接保持存活的超时
size_t request_size_limit; // 请求大小限制
int ssl_accept_timeout; // SSL 接受超时时间
};
// 设置服务器参数的默认值
static constexpr struct WFServerParams SERVER_PARAMS_DEFAULT =
{
.transport_type = TT_TCP, // 默认使用 TCP
.max_connections = 2000, // 默认最多 2000 个连接
.peer_response_timeout = 10 * 1000, // 默认对端响应超时 10 秒
.receive_timeout = -1, // 默认不超时
.keep_alive_timeout = 60 * 1000, // 默认连接保持存活 60 秒
.request_size_limit = (size_t)-1, // 请求大小限制为无限制
.ssl_accept_timeout = 10 * 1000, // SSL 接受超时设置为 10 秒
};
// 定义 WFServerBase 基类,用于建立服务器
class WFServerBase : protected CommService
{
public:
// 构造函数,接收服务器参数并初始化
WFServerBase(const struct WFServerParams *params) :
conn_count(0) // 初始化连接计数为 0
{
this->params = *params; // 保存服务器参数
this->unbind_finish = false; // 初始化解除绑定状态
this->listen_fd = -1; // 初始化监听文件描述符为无效值
}
public:
// 启动一个 TCP 服务器函数
/* 在指定端口上启动服务器IPv4 */
int start(unsigned short port)
{
return start(AF_INET, NULL, port, NULL, NULL);
}
/* 根据家庭类型启动服务器IPv4 或 IPv6 */
int start(int family, unsigned short port)
{
return start(family, NULL, port, NULL, NULL);
}
/* 使用主机名和端口启动服务器 */
int start(const char *host, unsigned short port)
{
return start(AF_INET, host, port, NULL, NULL);
}
/* 使用家庭类型、主机名和端口启动服务器 */
int start(int family, const char *host, unsigned short port)
{
return start(family, host, port, NULL, NULL);
}
/* 使用指定的地址绑定启动服务器 */
int start(const struct sockaddr *bind_addr, socklen_t addrlen)
{
return start(bind_addr, addrlen, NULL, NULL);
}
// 启动一个 SSL 服务器
/* 在指定端口启动 SSL 服务器 */
int start(unsigned short port, const char *cert_file, const char *key_file)
{
return start(AF_INET, NULL, port, cert_file, key_file);
}
/* 使用家庭类型和端口启动 SSL 服务器 */
int start(int family, unsigned short port,
const char *cert_file, const char *key_file)
{
return start(family, NULL, port, cert_file, key_file);
}
/* 使用主机名和端口启动 SSL 服务器 */
int start(const char *host, unsigned short port,
const char *cert_file, const char *key_file)
{
return start(AF_INET, host, port, cert_file, key_file);
}
/* 使用家庭类型、主机名和端口启动 SSL 服务器 */
int start(int family, const char *host, unsigned short port,
const char *cert_file, const char *key_file);
/* 使用指定文件描述符启动服务器,用于优雅重启或 SCTP 服务器 */
int serve(int listen_fd)
{
return serve(listen_fd, NULL, NULL);
}
int serve(int listen_fd, const char *cert_file, const char *key_file);
/* 停止服务器是一个阻塞操作 */
void stop()
{
this->shutdown(); // 关闭服务器
this->wait_finish(); // 等待完成
}
/* 非阻塞地终止服务器。用于停止多个服务器。
* 通常,调用 shutdown() 然后 wait_finish()。
* 但实际上,可以在其他线程中在 shutdown() 之前甚至在 start() 之前调用 wait_finish()。 */
void shutdown(); // 停止服务器
void wait_finish(); // 等待所有连接和任务完成
public:
// 获取当前连接数
size_t get_conn_count() const { return this->conn_count; }
/* 获取监听地址。这通常在服务器在随机端口上启动后使用start() 端口为 0。 */
int get_listen_addr(struct sockaddr *addr, socklen_t *addrlen) const
{
if (this->listen_fd >= 0)
return getsockname(this->listen_fd, addr, addrlen); // 获取当前的 socket 地址
errno = ENOTCONN; // 如果没有连接,设置错误号为没有连接
return -1; // 返回错误
}
// 获取服务器参数
const struct WFServerParams *get_params() const { return &this->params; }
protected:
/* 重写此函数以创建服务器的初始 SSL CTX */
virtual SSL_CTX *new_ssl_ctx(const char *cert_file, const char *key_file);
/* 重写此函数以实现支持 TLS SNI 的服务器。
* "servername" 如果客户端未设置主机名将为 NULL。
* 返回 NULL 表示服务器名称不受支持。 */
virtual SSL_CTX *get_server_ssl_ctx(const char *servername)
{
return this->get_ssl_ctx(); // 返回当前的 SSL 上下文
}
/* 这个函数可以在 'new_ssl_ctx' 的实现中使用。 */
static int ssl_ctx_callback(SSL *ssl, int *al, void *arg);
protected:
WFServerParams params; // 服务器参数结构体
protected:
// 创建新连接的方法
virtual int create_listen_fd();
virtual WFConnection *new_connection(int accept_fd); // 创建新连接
void delete_connection(WFConnection *conn); // 删除连接
private:
// 初始化服务器的方法
int init(const struct sockaddr *bind_addr, socklen_t addrlen,
const char *cert_file, const char *key_file);
virtual void handle_unbound(); // 处理解除绑定
protected:
std::atomic<size_t> conn_count; // 当前连接计数
private:
int listen_fd; // 监听文件描述符
bool unbind_finish; // 标记解除绑定是否完成
std::mutex mutex; // 互斥锁,用于线程安全
std::condition_variable cond; // 条件变量,用于线程间通知
class CommScheduler *scheduler; // 调度器
};
// 模板类,用于定义特定协议的服务器
template<class REQ, class RESP>
class WFServer : public WFServerBase
{
public:
// 构造函数,接收参数和处理函数
WFServer(const struct WFServerParams *params,
std::function<void (WFNetworkTask<REQ, RESP> *)> proc) :
WFServerBase(params), // 调用基类构造函数
process(std::move(proc)) // 移动处理函数,避免不必要的拷贝
{
}
// 构造函数,使用默认参数
WFServer(std::function<void (WFNetworkTask<REQ, RESP> *)> proc) :
WFServerBase(&SERVER_PARAMS_DEFAULT), // 调用基类构造函数,传入默认参数
process(std::move(proc)) // 移动处理函数
{
}
protected:
virtual CommSession *new_session(long long seq, CommConnection *conn); // 创建新会话
protected:
std::function<void (WFNetworkTask<REQ, RESP> *)> process; // 处理函数
};
// 创建新会话的方法,实现具体的会话处理
template<class REQ, class RESP>
CommSession *WFServer<REQ, RESP>::new_session(long long seq, CommConnection *conn)
{
using factory = WFNetworkTaskFactory<REQ, RESP>; // 使用工厂来创建任务
WFNetworkTask<REQ, RESP> *task; // 声明任务指针
task = factory::create_server_task(this, this->process); // 使用工厂创建任务
task->set_keep_alive(this->params.keep_alive_timeout); // 设置保持连接的超时
task->set_receive_timeout(this->params.receive_timeout); // 设置接收超时
task->get_req()->set_size_limit(this->params.request_size_limit); // 设置请求大小限制
return task; // 返回创建的会话任务
}
#endif // _WFSERVER_H_