TcpClient.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * Copyright (c) 2016 The ZLToolKit project authors. All Rights Reserved.
  3. *
  4. * This file is part of ZLToolKit(https://github.com/ZLMediaKit/ZLToolKit).
  5. *
  6. * Use of this source code is governed by MIT license that can be found in the
  7. * LICENSE file in the root of the source tree. All contributing project authors
  8. * may be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #ifndef NETWORK_TCPCLIENT_H
  11. #define NETWORK_TCPCLIENT_H
  12. #include <memory>
  13. #include "Socket.h"
  14. #include "Util/SSLBox.h"
  15. namespace toolkit {
  16. //Tcp客户端,Socket对象默认开始互斥锁
  17. class TcpClient : public SocketHelper {
  18. public:
  19. using Ptr = std::shared_ptr<TcpClient>;
  20. TcpClient(const EventPoller::Ptr &poller = nullptr);
  21. ~TcpClient() override;
  22. /**
  23. * 开始连接tcp服务器
  24. * @param url 服务器ip或域名
  25. * @param port 服务器端口
  26. * @param timeout_sec 超时时间,单位秒
  27. * @param local_port 本地端口
  28. */
  29. virtual void startConnect(const std::string &url, uint16_t port, float timeout_sec = 5, uint16_t local_port = 0);
  30. /**
  31. * 通过代理开始连接tcp服务器
  32. * @param url 服务器ip或域名
  33. * @proxy_host 代理ip
  34. * @proxy_port 代理端口
  35. * @param timeout_sec 超时时间,单位秒
  36. * @param local_port 本地端口
  37. */
  38. virtual void startConnectWithProxy(const std::string &url, const std::string &proxy_host, uint16_t proxy_port, float timeout_sec = 5, uint16_t local_port = 0){};
  39. /**
  40. * 主动断开连接
  41. * @param ex 触发onErr事件时的参数
  42. */
  43. void shutdown(const SockException &ex = SockException(Err_shutdown, "self shutdown")) override;
  44. /**
  45. * 连接中或已连接返回true,断开连接时返回false
  46. */
  47. virtual bool alive() const;
  48. /**
  49. * 设置网卡适配器,使用该网卡与服务器通信
  50. * @param local_ip 本地网卡ip
  51. */
  52. virtual void setNetAdapter(const std::string &local_ip);
  53. /**
  54. * 唯一标识
  55. */
  56. std::string getIdentifier() const override;
  57. protected:
  58. /**
  59. * 连接服务器结果回调
  60. * @param ex 成功与否
  61. */
  62. virtual void onConnect(const SockException &ex) = 0;
  63. /**
  64. * tcp连接成功后每2秒触发一次该事件
  65. */
  66. void onManager() override {}
  67. private:
  68. void onSockConnect(const SockException &ex);
  69. private:
  70. mutable std::string _id;
  71. std::string _net_adapter = "::";
  72. std::shared_ptr<Timer> _timer;
  73. //对象个数统计
  74. ObjectStatistic<TcpClient> _statistic;
  75. };
  76. //用于实现TLS客户端的模板对象
  77. template<typename TcpClientType>
  78. class TcpClientWithSSL : public TcpClientType {
  79. public:
  80. using Ptr = std::shared_ptr<TcpClientWithSSL>;
  81. template<typename ...ArgsType>
  82. TcpClientWithSSL(ArgsType &&...args):TcpClientType(std::forward<ArgsType>(args)...) {}
  83. ~TcpClientWithSSL() override {
  84. if (_ssl_box) {
  85. _ssl_box->flush();
  86. }
  87. }
  88. void onRecv(const Buffer::Ptr &buf) override {
  89. if (_ssl_box) {
  90. _ssl_box->onRecv(buf);
  91. } else {
  92. TcpClientType::onRecv(buf);
  93. }
  94. }
  95. ssize_t send(Buffer::Ptr buf) override {
  96. if (_ssl_box) {
  97. auto size = buf->size();
  98. _ssl_box->onSend(std::move(buf));
  99. return size;
  100. }
  101. return TcpClientType::send(std::move(buf));
  102. }
  103. //添加public_onRecv和public_send函数是解决较低版本gcc一个lambad中不能访问protected或private方法的bug
  104. inline void public_onRecv(const Buffer::Ptr &buf) {
  105. TcpClientType::onRecv(buf);
  106. }
  107. inline void public_send(const Buffer::Ptr &buf) {
  108. TcpClientType::send(std::move(const_cast<Buffer::Ptr &>(buf)));
  109. }
  110. void startConnect(const std::string &url, uint16_t port, float timeout_sec = 5, uint16_t local_port = 0) override {
  111. _host = url;
  112. TcpClientType::startConnect(url, port, timeout_sec, local_port);
  113. }
  114. void startConnectWithProxy(const std::string &url, const std::string &proxy_host, uint16_t proxy_port, float timeout_sec = 5, uint16_t local_port = 0) override {
  115. _host = url;
  116. TcpClientType::startConnect(proxy_host, proxy_port, timeout_sec, local_port);
  117. }
  118. bool overSsl() const override { return (bool)_ssl_box; }
  119. protected:
  120. void onConnect(const SockException &ex) override {
  121. if (!ex) {
  122. _ssl_box = std::make_shared<SSL_Box>(false);
  123. _ssl_box->setOnDecData([this](const Buffer::Ptr &buf) {
  124. public_onRecv(buf);
  125. });
  126. _ssl_box->setOnEncData([this](const Buffer::Ptr &buf) {
  127. public_send(buf);
  128. });
  129. if (!isIP(_host.data())) {
  130. //设置ssl域名
  131. _ssl_box->setHost(_host.data());
  132. }
  133. }
  134. TcpClientType::onConnect(ex);
  135. }
  136. /**
  137. * 重置ssl, 主要为了解决一些302跳转时http与https的转换
  138. */
  139. void setDoNotUseSSL() {
  140. _ssl_box.reset();
  141. }
  142. private:
  143. std::string _host;
  144. std::shared_ptr<SSL_Box> _ssl_box;
  145. };
  146. } /* namespace toolkit */
  147. #endif /* NETWORK_TCPCLIENT_H */