开发基于字节流协议的服务器(tcp,ssl,unix)
#include "net4cxx/net4cxx.h"
using namespace net4cxx;
class Echo: public Protocol, public std::enable_shared_from_this<MyProtocol> {
public:
void dataReceived(Byte *data, size_t length) override {
write(data, length);
}
};
class EchoFactory: public Factory {
public:
ProtocolPtr buildProtocol(const Address &address) override {
return std::make_shared<Echo>();
}
};
int main(int argc, char **argv) {
NET4CXX_PARSE_COMMAND_LINE(argc, argv);
Reactor reactor;
TCPServerEndpoint endpoint(&reactor, "28001");
endpoint.listen(std::make_unique<EchoFactory>());
reactor.run();
return 0;
}
- 以上实现了一个最简单的例子,将客户端发送过来的信息回写;
- 将TCPServerEndPoint替换成SSLServerEndPoint将会启动一个基于sslSocket的服务器;
- 将TCPServerEndPoint替换成UNIXServerEndPoint将会启动一个基于unixSocket的服务器;
- 后面会展示一种更好的服务器启动方式,切换协议无需修改任何代码.
class Echo: public Protocol, public std::enable_shared_from_this<MyProtocol> {
public:
void connectionMade() override {
NET4CXX_INFO(gAppLog, "Connection made");
}
void connectionLost(std::exception_ptr reason) override {
NET4CXX_INFO(gAppLog, "Connection lost");
}
void dataReceived(Byte *data, size_t length) override {
write(data, length);
loseConnection();
}
};
- 连接建立时将会回调connectionMade;
- 连接销毁时将会回调connectionLost;
- 调用loseConnection安全的关闭连接.
int main(int argc, char **argv) {
NET4CXX_PARSE_COMMAND_LINE(argc, argv);
Reactor reactor;
serverFromString(&reactor, "tcp:28001")->listen(std::make_unique<EchoFactory>());
serverFromString(&reactor, "ssl:28002:privateKey=test.key:certKey=test.crt")->listen(std::make_unique<EchoFactory>());
serverFromString(&reactor, "unix:/var/foo/bar")->listen(std::make_unique<MyFactory>());
reactor.run();
return 0;
}
- 以上代码展示了在一个进程内同时启动了一个tcp服务器,ssl服务器,unix服务器;
- 观察服务器的启动方式,发现只有字符串参数的值不同,如果我们从配置中读取这个字符串的话,切换协议无须更改一行代码,这也是推荐的方式;
开发基于字节流协议的客户端(tcp,ssl,unix)
#include "net4cxx/net4cxx.h"
using namespace net4cxx;
class WelcomeMessage: public Protocol, public std::enable_shared_from_this<WelcomeMessage> {
public:
void connectionMade() override {
write("Hello server, I am the client!");
loseConnection();
}
};
class WelcomeFactory: public ClientFactory {
public:
std::shared_ptr<Protocol> buildProtocol(const Address &address) override {
return std::make_shared<WelcomeMessage>();
}
};
int main(int argc, char **argv) {
NET4CXX_PARSE_COMMAND_LINE(argc, argv);
Reactor reactor;
reactor.connectTCP("localhost", "28001", std::make_unique<WelcomeFactory>());
reactor.run();
return 0;
}
- 以上实现了一个最简单的例子,客户端向服务器打了个招乎,随后关闭连接;
- 将connectTCP替换成connectSSL或者connectUNIX能分别建立ssl或者unix客户端连接;
- 与服务器一样支持从字符串构建客户端连接,调用clientFromString即可,不再赘述;
int main(int argc, char **argv) {
NET4CXX_PARSE_COMMAND_LINE(argc, argv);
Reactor reactor;
reactor.connectTCP("localhost", "28001", std::make_unique<OneShotFactory>(std::make_shared<WelcomeMessage>()));
reactor.run();
return 0;
}
- 使用内置的OneShotFactory可以指定总是返回某个固定的protocol,用户也无需创建自己的factory,这在服务器之间互联很有用;
class WelcomeFactory: public ReconnectingClientFactory {
public:
std::shared_ptr<Protocol> buildProtocol(const Address &address) override {
resetDelay();
return std::make_shared<WelcomeMessage>();
}
};
- 当继承自内建的ReconnectingClientFactory,连接断开时,会自动启用指数避让原则进行重连;
void run(bool installSignalHandlers=true);
- installSignalHandlers: 是否安装信号退出处理器
template <typename CallbackT>
DelayedCall callLater(double deadline, CallbackT &&callback);
template <typename CallbackT>
DelayedCall callLater(const Duration &deadline, CallbackT &&callback);
- deadline: 延迟多少秒触发
- callback: 回调函数,满足签名void ()
template <typename CallbackT>
DelayedCall callAt(time_t deadline, CallbackT &&callback);
template <typename CallbackT>
DelayedCall callAt(const Timestamp &deadline, CallbackT &&callback);
- deadline: 触发的绝对时间
- callback: 回调函数,满足签名void ()
template <typename CallbackT>
void addCallback(CallbackT &&callback);
- callback: 回调函数,满足签名void ()
template <typename CallbackT>
void addStopCallback(CallbackT &&callback);
- callback: 回调函数,满足签名void ()
ListenerPtr listenTCP(const std::string &port, std::unique_ptr<Factory> &&factory, const std::string &interface={});
- port: 端口号或服务名称
- factory: 协议工厂
- interface: 指定监听的ip地址或域名
ConnectorPtr connectTCP(const std::string &host, const std::string &port, std::unique_ptr<ClientFactory> &&factory,
double timeout=30.0, const Address &bindAddress={});
- host: 连接的服务器的ip地址或域名
- port: 连接的服务器的端口或服务名
- factory: 协议工厂
- timeout: 连接超时时间
- bindAddress: 为客户端套接字绑定一个指定的地址和端口
ListenerPtr listenSSL(const std::string &port, std::unique_ptr<Factory> &&factory, SSLOptionPtr sslOption,
const std::string &interface={});
- port: 端口号或服务名称
- factory: 协议工厂
- sslOption: ssl选项
- interface: 指定监听的ip地址或域名
ConnectorPtr connectSSL(const std::string &host, const std::string &port, std::unique_ptr<ClientFactory> &&factory,
SSLOptionPtr sslOption, double timeout=30.0, const Address &bindAddress={});
- host: 连接的服务器的ip地址或域名
- port: 连接的服务器的端口或服务名
- factory: 协议工厂
- sslOption: ssl选项
- timeout: 连接超时时间
- bindAddress: 为客户端套接字绑定一个指定的地址和端口
ListenerPtr listenUNIX(const std::string &path, std::unique_ptr<Factory> &&factory);
- path: 监听的文件路经
- factory: 协议工厂
ConnectorPtr connectUNIX(const std::string &path, std::unique_ptr<ClientFactory> &&factory, double timeout=30.0);
- path: 服务器的文件路经
- factory: 协议工厂
- timeout: 连接超时时间
Address();
Address(std::string address, unsigned short port);
- address: ip地址或文件路经(unix)
- port: 端口号, 对unix域地址无效
void setAddress(std::string &&address);
void setAddress(const std::string &address);
const std::string& getAddress() const
void setPort(unsigned short port);
unsigned short getPort() const;