阿里云服务器免费领卷啦。

捡代码论坛-最全的游戏源码下载技术网站!

 找回密码
 立 即 注 册

QQ登录

只需一步,快速开始

搜索
关于源码区的附件失效或欺骗帖, 处理办法
查看: 3070|回复: 1

基于libuv的TCP设计(一)

[复制链接]

4208

主题

210

回帖

12万

积分

管理员

管理员

Rank: 9Rank: 9Rank: 9

积分
126081
QQ
发表于 2017-4-1 16:47:42 | 显示全部楼层 |阅读模式

本人一直在寻找一个跨平台的网络库,boost与ACE比较庞大,不考虑。对比了libevent,libev,libuv后,最终选择了libuv.可libuv文档少,例子也简单,对于tcp只有个echo-server的例子。网上也找过对其封装的例子,如下


libsourcey库,封装了许多库。对libuv的封装跟其他代码耦合比较紧,难为剥离 http://sourcey.com/libuv-cpp-wrappers/
C++11封装的,可惜VS10未完全支持C++11 https://github.com/larroy/uvpp
C++封装的  https://github.com/keepallsimple/uvpp

       本人想实现一个raw tcp server,支持上万链接数的,网上找到的都没合适我的,没办法只能参照各例子自己封装了。

头文件
  1. /***************************************

  2. * @file tcpsocket.h

  3. * @brief 基于libuv封装的tcp服务器与客户端,使用log4z作日志工具

  4. * @details

  5. * @author phata, wqvbjhc@gmail.com

  6. * @date 2014-5-13

  7. * @mod 2014-5-13 phata 修正服务器与客户端的错误.现服务器支持多客户端连接

  8. 修改客户端测试代码,支持并发多客户端测试

  9. ****************************************/

  10. #ifndef TCPSocket_H

  11. #define TCPSocket_H

  12. #include "uv.h"

  13. #include <string>

  14. #include <list>

  15. #include <map>

  16. #define BUFFERSIZE (1024*1024)



  17. namespace uv

  18. {

  19. typedef void (*newconnect)(int clientid);

  20. typedef void (*server_recvcb)(int cliendid, const char* buf, int bufsize);

  21. typedef void (*client_recvcb)(const char* buf, int bufsize, void* userdata);



  22. class TCPServer;

  23. class clientdata

  24. {

  25. public:

  26. clientdata(int clientid):client_id(clientid),recvcb_(nullptr) {

  27. client_handle = (uv_tcp_t*)malloc(sizeof(*client_handle));

  28. client_handle->data = this;

  29. readbuffer = uv_buf_init((char*)malloc(BUFFERSIZE), BUFFERSIZE);

  30.         writebuffer = uv_buf_init((char*)malloc(BUFFERSIZE), BUFFERSIZE);

  31. }

  32. virtual ~clientdata() {

  33. free(readbuffer.base);

  34. readbuffer.base = nullptr;

  35. readbuffer.len = 0;



  36.         free(writebuffer.base);

  37.         writebuffer.base = nullptr;

  38.         writebuffer.len = 0;



  39. free(client_handle);

  40. client_handle = nullptr;

  41. }

  42. int client_id;//客户端id,惟一

  43. uv_tcp_t* client_handle;//客户端句柄

  44. TCPServer* tcp_server;//服务器句柄(保存是因为某些回调函数需要到)

  45. uv_buf_t readbuffer;//接受数据的buf

  46.     uv_buf_t writebuffer;//写数据的buf

  47. uv_write_t write_req;

  48. server_recvcb recvcb_;//接收数据回调给用户的函数

  49. };





  50. class TCPServer

  51. {

  52. public:

  53. TCPServer(uv_loop_t* loop = uv_default_loop());

  54. virtual ~TCPServer();

  55. static void StartLog(const char* logpath = nullptr);//启动日志,必须启动才会生成日志

  56. public:

  57. //基本函数

  58. bool Start(const char *ip, int port);//启动服务器,地址为IP4

  59. bool Start6(const char *ip, int port);//启动服务器,地址为IP6

  60. void close();



  61. bool setNoDelay(bool enable);

  62. bool setKeepAlive(int enable, unsigned int delay);



  63. const char* GetLastErrMsg() const {

  64. return errmsg_.c_str();

  65. };



  66. virtual int send(int clientid, const char* data, std::size_t len);

  67. virtual void setnewconnectcb(newconnect cb);

  68. virtual void setrecvcb(int clientid,server_recvcb cb);//设置接收回调函数,每个客户端各有一个

  69. protected:

  70. int GetAvailaClientID()const;//获取可用的client id

  71. bool DeleteClient(int clientid);//删除链表中的客户端

  72. //静态回调函数

  73. static void AfterServerRecv(uv_stream_t *client, ssize_t nread, const uv_buf_t* buf);

  74. static void AfterSend(uv_write_t *req, int status);

  75. static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);

  76. static void AfterServerClose(uv_handle_t *handle);

  77.     static void AfterClientClose(uv_handle_t *handle);

  78. static void acceptConnection(uv_stream_t *server, int status);



  79. private:

  80. bool init();

  81. bool run(int status = UV_RUN_DEFAULT);

  82. bool bind(const char* ip, int port);

  83. bool bind6(const char* ip, int port);

  84. bool listen(int backlog = 1024);





  85. uv_tcp_t server_;//服务器链接

  86. std::map<int,clientdata*> clients_list_;//子客户端链接

  87.     uv_mutex_t mutex_handle_;//保护clients_list_

  88. uv_loop_t *loop_;

  89. std::string errmsg_;

  90. newconnect newconcb_;

  91.     bool isinit_;//是否已初始化,用于close函数中判断

  92. };







  93. class TCPClient

  94. {

  95. //直接调用connect/connect6会进行连接

  96. public:

  97. TCPClient(uv_loop_t* loop = uv_default_loop());

  98. virtual ~TCPClient();

  99. static void StartLog(const char* logpath = nullptr);//启动日志,必须启动才会生成日志

  100. public:

  101. //基本函数

  102. virtual bool connect(const char* ip, int port);//启动connect线程,循环等待直到connect完成

  103. virtual bool connect6(const char* ip, int port);//启动connect线程,循环等待直到connect完成

  104. virtual int send(const char* data, std::size_t len);

  105. virtual void setrecvcb(client_recvcb cb, void* userdata);////设置接收回调函数,只有一个

  106. void close();



  107. //是否启用Nagle算法

  108. bool setNoDelay(bool enable);

  109. bool setKeepAlive(int enable, unsigned int delay);



  110. const char* GetLastErrMsg() const {

  111. return errmsg_.c_str();

  112. };

  113. protected:

  114. //静态回调函数

  115. static void AfterConnect(uv_connect_t* handle, int status);

  116. static void AfterClientRecv(uv_stream_t *client, ssize_t nread, const uv_buf_t* buf);

  117. static void AfterSend(uv_write_t *req, int status);

  118. static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);

  119. static void AfterClose(uv_handle_t *handle);



  120. static void ConnectThread(void* arg);//真正的connect线程

  121. static void ConnectThread6(void* arg);//真正的connect线程



  122. bool init();

  123. bool run(int status = UV_RUN_DEFAULT);

  124. private:

  125. enum {

  126. CONNECT_TIMEOUT,

  127. CONNECT_FINISH,

  128. CONNECT_ERROR,

  129. CONNECT_DIS,

  130. };

  131. uv_tcp_t client_;//客户端连接

  132. uv_loop_t *loop_;

  133. uv_write_t write_req_;//写时请求

  134. uv_connect_t connect_req_;//连接时请求

  135. uv_thread_t connect_threadhanlde_;//线程句柄

  136. std::string errmsg_;//错误信息

  137. uv_buf_t readbuffer_;//接受数据的buf

  138. uv_buf_t writebuffer_;//写数据的buf

  139. uv_mutex_t write_mutex_handle_;//保护write,保存前一write完成才进行下一write



  140. int connectstatus_;//连接状态

  141. client_recvcb recvcb_;//回调函数

  142. void* userdata_;//回调函数的用户数据

  143. std::string connectip_;//连接的服务器IP

  144. int connectport_;//连接的服务器端口号

  145.     bool isinit_;//是否已初始化,用于close函数中判断

  146. };



  147. }
复制代码


源文件

  1. #include "tcpsocket.h"

  2. #include "log4z.h"



  3. std::string GetUVError(int retcode)

  4. {

  5.     std::string err;

  6.     err = uv_err_name(retcode);

  7.     err +=":";

  8.     err += uv_strerror(retcode);

  9.     return std::move(err);

  10. }



  11. namespace uv

  12. {

  13.     /*****************************************TCP Server*************************************************************/

  14.     TCPServer::TCPServer(uv_loop_t* loop)

  15.         :newconcb_(nullptr), isinit_(false)

  16.     {

  17.         loop_ = loop;

  18.     }





  19.     TCPServer::~TCPServer()

  20.     {

  21.         close();

  22.         LOGI("tcp server exit.");

  23.     }



  24.     //初始化与关闭--服务器与客户端一致

  25.     bool TCPServer::init()

  26.     {

  27.         if (isinit_) {

  28.             return true;

  29.         }



  30.         if (!loop_) {

  31.             errmsg_ = "loop is null on tcp init.";

  32.             LOGE(errmsg_);

  33.             return false;

  34.         }

  35.         int iret = uv_mutex_init(&mutex_handle_);

  36.         if (iret) {

  37.             errmsg_ = GetUVError(iret);

  38.             LOGE(errmsg_);

  39.             return false;

  40.         }

  41.         iret = uv_tcp_init(loop_,&server_);

  42.         if (iret) {

  43.             errmsg_ = GetUVError(iret);

  44.             LOGE(errmsg_);

  45.             return false;

  46.         }

  47.         isinit_ = true;

  48.         server_.data = this;

  49.         //iret = uv_tcp_keepalive(&server_, 1, 60);//调用此函数后后续函数会调用出错

  50.         //if (iret) {

  51.         //    errmsg_ = GetUVError(iret);

  52.         //    return false;

  53.         //}

  54.         return true;

  55.     }



  56.     void TCPServer::close()

  57.     {

  58.         for (auto it = clients_list_.begin(); it!=clients_list_.end(); ++it) {

  59.             auto data = it->second;

  60.             uv_close((uv_handle_t*)data->client_handle,AfterClientClose);

  61.         }

  62.         clients_list_.clear();



  63.         LOGI("close server");

  64.         if (isinit_) {

  65.             uv_close((uv_handle_t*) &server_, AfterServerClose);

  66.             LOGI("close server");

  67.         }

  68.         isinit_ = false;

  69.         uv_mutex_destroy(&mutex_handle_);

  70.     }



  71.     bool TCPServer::run(int status)

  72.     {

  73.         LOGI("server runing.");

  74.         int iret = uv_run(loop_,(uv_run_mode)status);

  75.         if (iret) {

  76.             errmsg_ = GetUVError(iret);

  77.             LOGE(errmsg_);

  78.             return false;

  79.         }

  80.         return true;

  81.     }

  82.     //属性设置--服务器与客户端一致

  83.     bool TCPServer::setNoDelay(bool enable)

  84.     {

  85.         int iret = uv_tcp_nodelay(&server_, enable ? 1 : 0);

  86.         if (iret) {

  87.             errmsg_ = GetUVError(iret);

  88.             LOGE(errmsg_);

  89.             return false;

  90.         }

  91.         return true;

  92.     }



  93.     bool TCPServer::setKeepAlive(int enable, unsigned int delay)

  94.     {

  95.         int iret = uv_tcp_keepalive(&server_, enable , delay);

  96.         if (iret) {

  97.             errmsg_ = GetUVError(iret);

  98.             LOGE(errmsg_);

  99.             return false;

  100.         }

  101.         return true;

  102.     }



  103.     //作为server时的函数

  104.     bool TCPServer::bind(const char* ip, int port)

  105.     {

  106.         struct sockaddr_in bind_addr;

  107.         int iret = uv_ip4_addr(ip, port, &bind_addr);

  108.         if (iret) {

  109.             errmsg_ = GetUVError(iret);

  110.             LOGE(errmsg_);

  111.             return false;

  112.         }

  113.         iret = uv_tcp_bind(&server_, (const struct sockaddr*)&bind_addr,0);

  114.         if (iret) {

  115.             errmsg_ = GetUVError(iret);

  116.             LOGE(errmsg_);

  117.             return false;

  118.         }

  119.         LOGI("server bind ip="<<ip<<", port="<<port);

  120.         return true;

  121.     }



  122.     bool TCPServer::bind6(const char* ip, int port)

  123.     {

  124.         struct sockaddr_in6 bind_addr;

  125.         int iret = uv_ip6_addr(ip, port, &bind_addr);

  126.         if (iret) {

  127.             errmsg_ = GetUVError(iret);

  128.             LOGE(errmsg_);

  129.             return false;

  130.         }

  131.         iret = uv_tcp_bind(&server_, (const struct sockaddr*)&bind_addr,0);

  132.         if (iret) {

  133.             errmsg_ = GetUVError(iret);

  134.             LOGE(errmsg_);

  135.             return false;

  136.         }

  137.         LOGI("server bind ip="<<ip<<", port="<<port);

  138.         return true;

  139.     }



  140.     bool TCPServer::listen(int backlog)

  141.     {

  142.         int iret = uv_listen((uv_stream_t*) &server_, backlog, acceptConnection);

  143.         if (iret) {

  144.             errmsg_ = GetUVError(iret);

  145.             LOGE(errmsg_);

  146.             return false;

  147.         }

  148.         LOGI("server listen");

  149.         return true;

  150.     }



  151.     bool TCPServer::Start( const char *ip, int port )

  152.     {

  153.         close();

  154.         if (!init()) {

  155.             return false;

  156.         }

  157.         if (!bind(ip,port)) {

  158.             return false;

  159.         }

  160.         if (!listen(SOMAXCONN)) {

  161.             return false;

  162.         }

  163.         if (!run()) {

  164.             return false;

  165.         }

  166.         LOGI("start listen "<<ip<<": "<<port);

  167.         return true;

  168.     }



  169.     bool TCPServer::Start6( const char *ip, int port )

  170.     {

  171.         close();

  172.         if (!init()) {

  173.             return false;

  174.         }

  175.         if (!bind6(ip,port)) {

  176.             return false;

  177.         }

  178.         if (!listen(SOMAXCONN)) {

  179.             return false;

  180.         }

  181.         if (!run()) {

  182.             return false;

  183.         }

  184.         return true;

  185.     }



  186.     //服务器发送函数

  187.     int TCPServer::send(int clientid, const char* data, std::size_t len)

  188.     {

  189.         auto itfind = clients_list_.find(clientid);

  190.         if (itfind == clients_list_.end()) {

  191.             errmsg_ = "can't find cliendid ";

  192.             errmsg_ += std::to_string((long long)clientid);

  193.             LOGE(errmsg_);

  194.             return -1;

  195.         }

  196.         //自己控制data的生命周期直到write结束

  197.         if (itfind->second->writebuffer.len < len) {

  198.             itfind->second->writebuffer.base = (char*)realloc(itfind->second->writebuffer.base,len);

  199.             itfind->second->writebuffer.len = len;

  200.         }

  201.         memcpy(itfind->second->writebuffer.base,data,len);

  202.         uv_buf_t buf = uv_buf_init((char*)itfind->second->writebuffer.base,len);

  203.         int iret = uv_write(&itfind->second->write_req, (uv_stream_t*)itfind->second->client_handle, &buf, 1, AfterSend);

  204.         if (iret) {

  205.             errmsg_ = GetUVError(iret);

  206.             LOGE(errmsg_);

  207.             return false;

  208.         }

  209.         return true;

  210.     }



  211.     //服务器-新客户端函数

  212.     void TCPServer::acceptConnection(uv_stream_t *server, int status)

  213.     {

  214.         if (!server->data) {

  215.             return;

  216.         }

  217.         TCPServer *tcpsock = (TCPServer *)server->data;

  218.         int clientid = tcpsock->GetAvailaClientID();

  219.         clientdata* cdata = new clientdata(clientid);//uv_close回调函数中释放

  220.         cdata->tcp_server = tcpsock;//保存服务器的信息

  221.         int iret = uv_tcp_init(tcpsock->loop_, cdata->client_handle);//析构函数释放

  222.         if (iret) {

  223.             delete cdata;

  224.             tcpsock->errmsg_ = GetUVError(iret);

  225.             LOGE(tcpsock->errmsg_);

  226.             return;

  227.         }

  228.         iret = uv_accept((uv_stream_t*)&tcpsock->server_, (uv_stream_t*) cdata->client_handle);

  229.         if ( iret) {

  230.             tcpsock->errmsg_ = GetUVError(iret);

  231.             uv_close((uv_handle_t*) cdata->client_handle, NULL);

  232.             delete cdata;

  233.             LOGE(tcpsock->errmsg_);

  234.             return;

  235.         }

  236.         tcpsock->clients_list_.insert(std::make_pair(clientid,cdata));//加入到链接队列

  237.         if (tcpsock->newconcb_) {

  238.             tcpsock->newconcb_(clientid);

  239.         }

  240.         LOGI("new client("<<cdata->client_handle<<") id="<< clientid);

  241.         iret = uv_read_start((uv_stream_t*)cdata->client_handle, onAllocBuffer, AfterServerRecv);//服务器开始接收客户端的数据

  242.         return;

  243.     }



  244.     //服务器-接收数据回调函数

  245.     void TCPServer::setrecvcb(int clientid, server_recvcb cb )

  246.     {

  247.         auto itfind = clients_list_.find(clientid);

  248.         if (itfind != clients_list_.end()) {

  249.             itfind->second->recvcb_ = cb;

  250.         }

  251.     }



  252.     //服务器-新链接回调函数

  253.     void TCPServer::setnewconnectcb(newconnect cb )

  254.     {

  255.         newconcb_ = cb;

  256.     }



  257.     //服务器分析空间函数

  258.     void TCPServer::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)

  259.     {

  260.         if (!handle->data) {

  261.             return;

  262.         }

  263.         clientdata *client = (clientdata*)handle->data;

  264.         *buf = client->readbuffer;

  265.     }



  266.     void TCPServer::AfterServerRecv(uv_stream_t *handle, ssize_t nread, const uv_buf_t* buf)

  267.     {

  268.         if (!handle->data) {

  269.             return;

  270.         }

  271.         clientdata *client = (clientdata*)handle->data;//服务器的recv带的是clientdata

  272.         if (nread < 0) {/* Error or EOF */

  273.             TCPServer *server = (TCPServer *)client->tcp_server;

  274.             if (nread == UV_EOF) {

  275.                 fprintf(stdout,"客户端(%d)连接断开,关闭此客户端\n",client->client_id);

  276.                 LOGW("客户端("<<client->client_id<<")主动断开");

  277.             } else if (nread == UV_ECONNRESET) {

  278.                 fprintf(stdout,"客户端(%d)异常断开\n",client->client_id);

  279.                 LOGW("客户端("<<client->client_id<<")异常断开");

  280.             } else {

  281.                 fprintf(stdout,"%s\n",GetUVError(nread));

  282.                 LOGW("客户端("<<client->client_id<<")异常断开:"<<GetUVError(nread));

  283.             }

  284.             server->DeleteClient(client->client_id);//连接断开,关闭客户端

  285.             return;

  286.         } else if (0 == nread) {/* Everything OK, but nothing read. */



  287.         } else if (client->recvcb_) {

  288.             client->recvcb_(client->client_id,buf->base,nread);

  289.         }

  290.     }



  291.     //服务器与客户端一致

  292.     void TCPServer::AfterSend(uv_write_t *req, int status)

  293.     {

  294.         if (status < 0) {

  295.             LOGE("发送数据有误:"<<GetUVError(status));

  296.             fprintf(stderr, "Write error %s\n", GetUVError(status));

  297.         }

  298.     }



  299.     void TCPServer::AfterServerClose(uv_handle_t *handle)

  300.     {

  301.         //服务器,不需要做什么

  302.     }



  303.     void TCPServer::AfterClientClose(uv_handle_t *handle)

  304.     {

  305.         clientdata *cdata = (clientdata*)handle->data;

  306.         LOGI("client "<<cdata->client_id<<" had closed.");

  307.         delete cdata;

  308.     }



  309.     int TCPServer::GetAvailaClientID() const

  310.     {

  311.         static int s_id = 0;

  312.         return ++s_id;

  313.     }



  314.     bool TCPServer::DeleteClient( int clientid )

  315.     {

  316.         uv_mutex_lock(&mutex_handle_);

  317.         auto itfind = clients_list_.find(clientid);

  318.         if (itfind == clients_list_.end()) {

  319.             errmsg_ = "can't find client ";

  320.             errmsg_ += std::to_string((long long)clientid);

  321.             LOGE(errmsg_);

  322.             uv_mutex_unlock(&mutex_handle_);

  323.             return false;

  324.         }

  325.         if (uv_is_active((uv_handle_t*)itfind->second->client_handle)) {

  326.             uv_read_stop((uv_stream_t*)itfind->second->client_handle);

  327.         }

  328.         uv_close((uv_handle_t*)itfind->second->client_handle,AfterClientClose);



  329.         clients_list_.erase(itfind);

  330.         LOGI("删除客户端"<<clientid);

  331.         uv_mutex_unlock(&mutex_handle_);

  332.         return true;

  333.     }





  334.     void TCPServer::StartLog( const char* logpath /*= nullptr*/ )

  335.     {

  336.         zsummer::log4z::ILog4zManager::GetInstance()->SetLoggerMonthdir(LOG4Z_MAIN_LOGGER_ID, true);

  337.         zsummer::log4z::ILog4zManager::GetInstance()->SetLoggerDisplay(LOG4Z_MAIN_LOGGER_ID,false);

  338.         zsummer::log4z::ILog4zManager::GetInstance()->SetLoggerLevel(LOG4Z_MAIN_LOGGER_ID,LOG_LEVEL_DEBUG);

  339.         zsummer::log4z::ILog4zManager::GetInstance()->SetLoggerLimitSize(LOG4Z_MAIN_LOGGER_ID,100);

  340.         if (logpath) {

  341.             zsummer::log4z::ILog4zManager::GetInstance()->SetLoggerPath(LOG4Z_MAIN_LOGGER_ID,logpath);

  342.         }

  343.         zsummer::log4z::ILog4zManager::GetInstance()->Start();

  344.     }





  345.     /*****************************************TCP Client*************************************************************/

  346.     TCPClient::TCPClient(uv_loop_t* loop)

  347.         :recvcb_(nullptr),userdata_(nullptr)

  348.         ,connectstatus_(CONNECT_DIS)

  349.         , isinit_(false)

  350.     {

  351.         readbuffer_ = uv_buf_init((char*) malloc(BUFFERSIZE), BUFFERSIZE);

  352.         writebuffer_ = uv_buf_init((char*) malloc(BUFFERSIZE), BUFFERSIZE);

  353.         loop_ = loop;

  354.         connect_req_.data = this;

  355.         write_req_.data = this;

  356.     }





  357.     TCPClient::~TCPClient()

  358.     {

  359.         free(readbuffer_.base);

  360.         readbuffer_.base = nullptr;

  361.         readbuffer_.len = 0;

  362.         free(writebuffer_.base);

  363.         writebuffer_.base = nullptr;

  364.         writebuffer_.len = 0;

  365.         close();

  366.         LOGI("客户端("<<this<<")退出");

  367.     }

  368.     //初始化与关闭--服务器与客户端一致

  369.     bool TCPClient::init()

  370.     {

  371.         if (isinit_) {

  372.             return true;

  373.         }



  374.         if (!loop_) {

  375.             errmsg_ = "loop is null on tcp init.";

  376.             LOGE(errmsg_);

  377.             return false;

  378.         }

  379.         int iret = uv_tcp_init(loop_,&client_);

  380.         if (iret) {

  381.             errmsg_ = GetUVError(iret);

  382.             LOGE(errmsg_);

  383.             return false;

  384.         }

  385.         iret = uv_mutex_init(&write_mutex_handle_);

  386.         if (iret) {

  387.             errmsg_ = GetUVError(iret);

  388.             LOGE(errmsg_);

  389.             return false;

  390.         }

  391.         isinit_ = true;

  392.         fprintf(stdout,"客户端(%p) init type = %d\n",&client_,client_.type);

  393.         client_.data = this;

  394.         //iret = uv_tcp_keepalive(&client_, 1, 60);//

  395.         //if (iret) {

  396.         // errmsg_ = GetUVError(iret);

  397.         // return false;

  398.         //}

  399.         LOGI("客户端("<<this<<")Init");

  400.         return true;

  401.     }



  402.     void TCPClient::close()

  403.     {

  404.         if (!isinit_) {

  405.             return;

  406.         }

  407.         uv_mutex_destroy(&write_mutex_handle_);

  408.         uv_close((uv_handle_t*) &client_, AfterClose);

  409.         LOGI("客户端("<<this<<")close");

  410.         isinit_ = false;

  411.     }



  412.     bool TCPClient::run(int status)

  413.     {

  414.         LOGI("客户端("<<this<<")run");

  415.         int iret = uv_run(loop_,(uv_run_mode)status);

  416.         if (iret) {

  417.             errmsg_ = GetUVError(iret);

  418.             LOGE(errmsg_);

  419.             return false;

  420.         }

  421.         return true;

  422.     }



  423.     //属性设置--服务器与客户端一致

  424.     bool TCPClient::setNoDelay(bool enable)

  425.     {

  426.         //http://blog.csdn.net/u011133100/article/details/21485983

  427.         int iret = uv_tcp_nodelay(&client_, enable ? 1 : 0);

  428.         if (iret) {

  429.             errmsg_ = GetUVError(iret);

  430.             LOGE(errmsg_);

  431.             return false;

  432.         }

  433.         return true;

  434.     }



  435.     bool TCPClient::setKeepAlive(int enable, unsigned int delay)

  436.     {

  437.         int iret = uv_tcp_keepalive(&client_, enable , delay);

  438.         if (iret) {

  439.             errmsg_ = GetUVError(iret);

  440.             LOGE(errmsg_);

  441.             return false;

  442.         }

  443.         return true;

  444.     }



  445.     //作为client的connect函数

  446.     bool TCPClient::connect(const char* ip, int port)

  447.     {

  448.         close();

  449.         init();

  450.         connectip_ = ip;

  451.         connectport_ = port;

  452.         LOGI("客户端("<<this<<")start connect to server("<<ip<<":"<<port<<")");

  453.         int iret = uv_thread_create(&connect_threadhanlde_, ConnectThread, this);//触发AfterConnect才算真正连接成功,所以用线程

  454.         if (iret) {

  455.             errmsg_ = GetUVError(iret);

  456.             LOGE(errmsg_);

  457.             return false;

  458.         }

  459.         while ( connectstatus_ == CONNECT_DIS) {

  460. #if defined (WIN32) || defined(_WIN32)

  461.             Sleep(100);

  462. #else

  463.             usleep((100) * 1000)

  464. #endif

  465.         }

  466.         return connectstatus_ == CONNECT_FINISH;

  467.     }



  468.     bool TCPClient::connect6(const char* ip, int port)

  469.     {

  470.         close();

  471.         init();

  472.         connectip_ = ip;

  473.         connectport_ = port;

  474.         LOGI("客户端("<<this<<")start connect to server("<<ip<<":"<<port<<")");

  475.         int iret = uv_thread_create(&connect_threadhanlde_, ConnectThread6, this);//触发AfterConnect才算真正连接成功,所以用线程

  476.         if (iret) {

  477.             errmsg_ = GetUVError(iret);

  478.             LOGE(errmsg_);

  479.             return false;

  480.         }

  481.         while ( connectstatus_ == CONNECT_DIS) {

  482.             //fprintf(stdout,"client(%p) wait, connect status %d\n",this,connectstatus_);

  483. #if defined (WIN32) || defined(_WIN32)

  484.             Sleep(100);

  485. #else

  486.             usleep((100) * 1000)

  487. #endif

  488.         }

  489.         return connectstatus_ == CONNECT_FINISH;

  490.     }



  491.     void TCPClient::ConnectThread( void* arg )

  492.     {

  493.         TCPClient *pclient = (TCPClient*)arg;

  494.         fprintf(stdout,"client(%p) ConnectThread start\n",pclient);

  495.         struct sockaddr_in bind_addr;

  496.         int iret = uv_ip4_addr(pclient->connectip_.c_str(), pclient->connectport_, &bind_addr);

  497.         if (iret) {

  498.             pclient->errmsg_ = GetUVError(iret);

  499.             LOGE(pclient->errmsg_);

  500.             return;

  501.         }

  502.         iret = uv_tcp_connect(&pclient->connect_req_, &pclient->client_, (const sockaddr*)&bind_addr, AfterConnect);

  503.         if (iret) {

  504.             pclient->errmsg_ = GetUVError(iret);

  505.             LOGE(pclient->errmsg_);

  506.             return;

  507.         }

  508.         fprintf(stdout,"client(%p) ConnectThread end, connect status %d\n",pclient, pclient->connectstatus_);

  509.         pclient->run();

  510.     }





  511.     void TCPClient::ConnectThread6( void* arg )

  512.     {

  513.         TCPClient *pclient = (TCPClient*)arg;

  514.         LOGI("客户端("<<pclient<<")Enter Connect Thread.");

  515.         fprintf(stdout,"client(%p) ConnectThread start\n",pclient);

  516.         struct sockaddr_in6 bind_addr;

  517.         int iret = uv_ip6_addr(pclient->connectip_.c_str(), pclient->connectport_, &bind_addr);

  518.         if (iret) {

  519.             pclient->errmsg_ = GetUVError(iret);

  520.             LOGE(pclient->errmsg_);

  521.             return;

  522.         }

  523.         iret = uv_tcp_connect(&pclient->connect_req_, &pclient->client_, (const sockaddr*)&bind_addr, AfterConnect);

  524.         if (iret) {

  525.             pclient->errmsg_ = GetUVError(iret);

  526.             LOGE(pclient->errmsg_);

  527.             return;

  528.         }

  529.         fprintf(stdout,"client(%p) ConnectThread end, connect status %d\n",pclient, pclient->connectstatus_);

  530.         LOGI("客户端("<<pclient<<")Leave Connect Thread. connect status "<<pclient->connectstatus_);

  531.         pclient->run();

  532.     }



  533.     void TCPClient::AfterConnect(uv_connect_t* handle, int status)

  534.     {

  535.         fprintf(stdout,"start after connect\n");

  536.         TCPClient *pclient = (TCPClient*)handle->handle->data;

  537.         if (status) {

  538.             pclient->connectstatus_ = CONNECT_ERROR;

  539.             fprintf(stdout,"connect error:%s\n",GetUVError(status));

  540.             return;

  541.         }



  542.         int iret = uv_read_start(handle->handle, onAllocBuffer, AfterClientRecv);//客户端开始接收服务器的数据

  543.         if (iret) {

  544.             fprintf(stdout,"uv_read_start error:%s\n",GetUVError(iret));

  545.             pclient->connectstatus_ = CONNECT_ERROR;

  546.         } else {

  547.             pclient->connectstatus_ = CONNECT_FINISH;

  548.         }

  549.         LOGI("客户端("<<pclient<<")run");

  550.         fprintf(stdout,"end after connect\n");

  551.     }



  552.     //客户端的发送函数

  553.     int TCPClient::send(const char* data, std::size_t len)

  554.     {

  555.         //自己控制data的生命周期直到write结束

  556.         if (!data || len <= 0) {

  557.             errmsg_ = "send data is null or len less than zero.";

  558.             return 0;

  559.         }



  560.         uv_mutex_lock(&write_mutex_handle_);

  561.         if (writebuffer_.len < len) {

  562.             writebuffer_.base = (char*)realloc(writebuffer_.base,len);

  563.             writebuffer_.len = len;

  564.         }

  565.         memcpy(writebuffer_.base,data,len);

  566.         uv_buf_t buf = uv_buf_init((char*)writebuffer_.base,len);

  567.         int iret = uv_write(&write_req_, (uv_stream_t*)&client_, &buf, 1, AfterSend);

  568.         if (iret) {

  569.             uv_mutex_unlock(&write_mutex_handle_);

  570.             errmsg_ = GetUVError(iret);

  571.             LOGE(errmsg_);

  572.             return false;

  573.         }

  574.         return true;

  575.     }



  576.     //客户端-接收数据回调函数

  577.     void TCPClient::setrecvcb(client_recvcb cb, void* userdata )

  578.     {

  579.         recvcb_ = cb;

  580.         userdata_ = userdata;

  581.     }



  582.     //客户端分析空间函数

  583.     void TCPClient::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)

  584.     {

  585.         if (!handle->data) {

  586.             return;

  587.         }

  588.         TCPClient *client = (TCPClient*)handle->data;

  589.         *buf = client->readbuffer_;

  590.     }





  591.     void TCPClient::AfterClientRecv(uv_stream_t *handle, ssize_t nread, const uv_buf_t* buf)

  592.     {

  593.         if (!handle->data) {

  594.             return;

  595.         }

  596.         TCPClient *client = (TCPClient*)handle->data;//服务器的recv带的是TCPClient

  597.         if (nread < 0) {

  598.             if (nread == UV_EOF) {

  599.                 fprintf(stdout,"服务器(%p)主动断开\n",handle);

  600.                 LOGW("服务器主动断开");

  601.             } else if (nread == UV_ECONNRESET) {

  602.                 fprintf(stdout,"服务器(%p)异常断开\n",handle);

  603.                 LOGW("服务器异常断开");

  604.             } else {

  605.                 fprintf(stdout,"服务器(%p)异常断开:%s\n",handle,GetUVError(nread));

  606.                 LOGW("服务器异常断开"<<GetUVError(nread));

  607.             }

  608.             uv_close((uv_handle_t*)handle, AfterClose);

  609.             return;

  610.         }

  611.         if (nread > 0 && client->recvcb_) {

  612.             client->recvcb_(buf->base,nread,client->userdata_);

  613.         }

  614.     }



  615.     //服务器与客户端一致

  616.     void TCPClient::AfterSend(uv_write_t *req, int status)

  617.     {

  618.         TCPClient *client = (TCPClient *)req->handle->data;

  619.         uv_mutex_unlock(&client->write_mutex_handle_);

  620.         if (status < 0) {

  621.             LOGE("发送数据有误:"<<GetUVError(status));

  622.             fprintf(stderr, "Write error %s\n", GetUVError(status));

  623.         }

  624.     }

  625.     //服务器与客户端一致

  626.     void TCPClient::AfterClose(uv_handle_t *handle)

  627.     {

  628.         fprintf(stdout,"客户端(%p)已close\n",handle);

  629.         LOGI("客户端("<<handle<<")已close");

  630.     }



  631.     void TCPClient::StartLog( const char* logpath /*= nullptr*/ )

  632.     {

  633.         zsummer::log4z::ILog4zManager::GetInstance()->SetLoggerMonthdir(LOG4Z_MAIN_LOGGER_ID, true);

  634.         zsummer::log4z::ILog4zManager::GetInstance()->SetLoggerDisplay(LOG4Z_MAIN_LOGGER_ID,false);

  635.         zsummer::log4z::ILog4zManager::GetInstance()->SetLoggerLevel(LOG4Z_MAIN_LOGGER_ID,LOG_LEVEL_DEBUG);

  636.         zsummer::log4z::ILog4zManager::GetInstance()->SetLoggerLimitSize(LOG4Z_MAIN_LOGGER_ID,100);

  637.         if (logpath) {

  638.             zsummer::log4z::ILog4zManager::GetInstance()->SetLoggerPath(LOG4Z_MAIN_LOGGER_ID,logpath);

  639.         }

  640.         zsummer::log4z::ILog4zManager::GetInstance()->Start();

  641.     }



  642. }
复制代码


原文地址:
  1. http://www.cnblogs.com/wqvbjhc/p/3757582.html
复制代码



捡代码论坛-最全的游戏源码下载技术网站! - 论坛版权郑重声明:
1、本主题所有言论和图片纯属会员个人意见,与本论坛立场无关
2、本站所有主题由该帖子作者发表,该帖子作者与捡代码论坛-最全的游戏源码下载技术网站!享有帖子相关版权
3、捡代码论坛版权,详细了解请点击。
4、本站所有内容均由互联网收集整理、网友上传,并且以计算机技术研究交流为目的,仅供大家参考、学习,不存在任何商业目的与商业用途。
5、若您需要商业运营或用于其他商业活动,请您购买正版授权并合法使用。 我们不承担任何技术及版权问题,且不对任何资源负法律责任。
6、如无法链接失效或侵犯版权,请给我们来信:jiandaima@foxmail.com

回复

使用道具 举报

4208

主题

210

回帖

12万

积分

管理员

管理员

Rank: 9Rank: 9Rank: 9

积分
126081
QQ
 楼主| 发表于 2017-4-3 16:44:01 | 显示全部楼层
登录可见评论
回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | 立 即 注 册

本版积分规则

技术支持
在线咨询
QQ咨询
3351529868

QQ|手机版|小黑屋|捡代码论坛-专业源码分享下载 ( 陕ICP备15015195号-1|网站地图

GMT+8, 2024-3-29 14:25

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表