libuv网络库的TCP服务端与客户端

来源:互联网 发布:移动云计算 编辑:程序博客网 时间:2024/06/15 08:40

本人一直在寻找一个跨平台的网络库,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,支持上万链接数的,网上找到的都没合适我的,没办法只能参照各例子自己封装了

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /*************************************** 
  2. * @file     tcpsocket.h 
  3. * @brief    基于libuv封装的tcp服务器与客户端,使用log4z作日志工具 
  4. * @details 
  5. * @author   陈吉宏, 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.   
  18. namespace uv  
  19. {  
  20. typedef void (*newconnect)(int clientid);  
  21. typedef void (*server_recvcb)(int cliendid, const char* buf, int bufsize);  
  22. typedef void (*client_recvcb)(const char* buf, int bufsize, void* userdata);  
  23.   
  24. class TCPServer;  
  25. class clientdata  
  26. {  
  27. public:  
  28.     clientdata(int clientid):client_id(clientid),recvcb_(nullptr) {  
  29.         client_handle = (uv_tcp_t*)malloc(sizeof(*client_handle));  
  30.         client_handle->data = this;  
  31.         readbuffer = uv_buf_init((char*)malloc(BUFFERSIZE), BUFFERSIZE);  
  32.         writebuffer = uv_buf_init((char*)malloc(BUFFERSIZE), BUFFERSIZE);  
  33.     }  
  34.     virtual ~clientdata() {  
  35.         free(readbuffer.base);  
  36.         readbuffer.base = nullptr;  
  37.         readbuffer.len = 0;  
  38.   
  39.         free(writebuffer.base);  
  40.         writebuffer.base = nullptr;  
  41.         writebuffer.len = 0;  
  42.   
  43.         free(client_handle);  
  44.         client_handle = nullptr;  
  45.     }  
  46.     int client_id;//客户端id,惟一  
  47.     uv_tcp_t* client_handle;//客户端句柄  
  48.     TCPServer* tcp_server;//服务器句柄(保存是因为某些回调函数需要到)  
  49.     uv_buf_t readbuffer;//接受数据的buf  
  50.     uv_buf_t writebuffer;//写数据的buf  
  51.     uv_write_t write_req;  
  52.     server_recvcb recvcb_;//接收数据回调给用户的函数  
  53. };  
  54.   
  55.   
  56. class TCPServer  
  57. {  
  58. public:  
  59.     TCPServer(uv_loop_t* loop = uv_default_loop());  
  60.     virtual ~TCPServer();  
  61.     static void StartLog(const char* logpath = nullptr);//启动日志,必须启动才会生成日志  
  62. public:  
  63.     //基本函数  
  64.     bool Start(const char *ip, int port);//启动服务器,地址为IP4  
  65.     bool Start6(const char *ip, int port);//启动服务器,地址为IP6  
  66.     void close();  
  67.   
  68.     bool setNoDelay(bool enable);  
  69.     bool setKeepAlive(int enable, unsigned int delay);  
  70.   
  71.     const char* GetLastErrMsg() const {  
  72.         return errmsg_.c_str();  
  73.     };  
  74.   
  75.     virtual int  send(int clientid, const char* data, std::size_t len);  
  76.     virtual void setnewconnectcb(newconnect cb);  
  77.     virtual void setrecvcb(int clientid,server_recvcb cb);//设置接收回调函数,每个客户端各有一个  
  78. protected:  
  79.     int GetAvailaClientID()const;//获取可用的client id  
  80.     bool DeleteClient(int clientid);//删除链表中的客户端  
  81.     //静态回调函数  
  82.     static void AfterServerRecv(uv_stream_t *client, ssize_t nread, const uv_buf_t* buf);  
  83.     static void AfterSend(uv_write_t *req, int status);  
  84.     static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);  
  85.     static void AfterServerClose(uv_handle_t *handle);  
  86.     static void AfterClientClose(uv_handle_t *handle);  
  87.     static void acceptConnection(uv_stream_t *server, int status);  
  88.   
  89. private:  
  90.     bool init();  
  91.     bool run(int status = UV_RUN_DEFAULT);  
  92.     bool bind(const char* ip, int port);  
  93.     bool bind6(const char* ip, int port);  
  94.     bool listen(int backlog = 1024);  
  95.   
  96.   
  97.     uv_tcp_t server_;//服务器链接  
  98.     std::map<int,clientdata*> clients_list_;//子客户端链接  
  99.     uv_mutex_t mutex_handle_;//保护clients_list_  
  100.     uv_loop_t *loop_;  
  101.     std::string errmsg_;  
  102.     newconnect newconcb_;  
  103.     bool isinit_;//是否已初始化,用于close函数中判断  
  104. };  
  105.   
  106.   
  107.   
  108. class TCPClient  
  109. {  
  110.     //直接调用connect/connect6会进行连接  
  111. public:  
  112.     TCPClient(uv_loop_t* loop = uv_default_loop());  
  113.     virtual ~TCPClient();  
  114.     static void StartLog(const char* logpath = nullptr);//启动日志,必须启动才会生成日志  
  115. public:  
  116.     //基本函数  
  117.     virtual bool connect(const char* ip, int port);//启动connect线程,循环等待直到connect完成  
  118.     virtual bool connect6(const char* ip, int port);//启动connect线程,循环等待直到connect完成  
  119.     virtual int  send(const char* data, std::size_t len);  
  120.     virtual void setrecvcb(client_recvcb cb, void* userdata);////设置接收回调函数,只有一个  
  121.     void close();  
  122.   
  123.     //是否启用Nagle算法  
  124.     bool setNoDelay(bool enable);  
  125.     bool setKeepAlive(int enable, unsigned int delay);  
  126.   
  127.     const char* GetLastErrMsg() const {  
  128.         return errmsg_.c_str();  
  129.     };  
  130. protected:  
  131.     //静态回调函数  
  132.     static void AfterConnect(uv_connect_t* handle, int status);  
  133.     static void AfterClientRecv(uv_stream_t *client, ssize_t nread, const uv_buf_t* buf);  
  134.     static void AfterSend(uv_write_t *req, int status);  
  135.     static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);  
  136.     static void AfterClose(uv_handle_t *handle);  
  137.   
  138.     static void ConnectThread(void* arg);//真正的connect线程  
  139.     static void ConnectThread6(void* arg);//真正的connect线程  
  140.   
  141.     bool init();  
  142.     bool run(int status = UV_RUN_DEFAULT);  
  143. private:  
  144.     enum {  
  145.         CONNECT_TIMEOUT,  
  146.         CONNECT_FINISH,  
  147.         CONNECT_ERROR,  
  148.         CONNECT_DIS,  
  149.     };  
  150.     uv_tcp_t client_;//客户端连接  
  151.     uv_loop_t *loop_;  
  152.     uv_write_t write_req_;//写时请求  
  153.     uv_connect_t connect_req_;//连接时请求  
  154.     uv_thread_t connect_threadhanlde_;//线程句柄  
  155.     std::string errmsg_;//错误信息  
  156.     uv_buf_t readbuffer_;//接受数据的buf  
  157.     uv_buf_t writebuffer_;//写数据的buf  
  158.     uv_mutex_t write_mutex_handle_;//保护write,保存前一write完成才进行下一write  
  159.   
  160.     int connectstatus_;//连接状态  
  161.     client_recvcb recvcb_;//回调函数  
  162.     void* userdata_;//回调函数的用户数据  
  163.     std::string connectip_;//连接的服务器IP  
  164.     int connectport_;//连接的服务器端口号  
  165.     bool isinit_;//是否已初始化,用于close函数中判断  
  166. };  
  167.   
  168. }  
  169.   
  170.   
  171. #endif // TCPSocket_H  
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include "tcpsocket.h"  
  2. #include "log4z.h"  
  3.   
  4. std::string GetUVError(int retcode)  
  5. {  
  6.     std::string err;  
  7.     err = uv_err_name(retcode);  
  8.     err +=":";  
  9.     err += uv_strerror(retcode);  
  10.     return std::move(err);  
  11. }  
  12.   
  13. namespace uv  
  14. {  
  15. /*****************************************TCP Server*************************************************************/  
  16. TCPServer::TCPServer(uv_loop_t* loop)  
  17.     :newconcb_(nullptr), isinit_(false)  
  18. {  
  19.     loop_ = loop;  
  20. }  
  21.   
  22.   
  23. TCPServer::~TCPServer()  
  24. {  
  25.     close();  
  26.     LOGI("tcp server exit.");  
  27. }  
  28.   
  29. //初始化与关闭--服务器与客户端一致  
  30. bool TCPServer::init()  
  31. {  
  32.     if (isinit_) {  
  33.         return true;  
  34.     }  
  35.   
  36.     if (!loop_) {  
  37.         errmsg_ = "loop is null on tcp init.";  
  38.         LOGE(errmsg_);  
  39.         return false;  
  40.     }  
  41.     int iret = uv_mutex_init(&mutex_handle_);  
  42.     if (iret) {  
  43.         errmsg_ = GetUVError(iret);  
  44.         LOGE(errmsg_);  
  45.         return false;  
  46.     }  
  47.     iret = uv_tcp_init(loop_,&server_);  
  48.     if (iret) {  
  49.         errmsg_ = GetUVError(iret);  
  50.         LOGE(errmsg_);  
  51.         return false;  
  52.     }  
  53.     isinit_ = true;  
  54.     server_.data = this;  
  55.     //iret = uv_tcp_keepalive(&server_, 1, 60);//调用此函数后后续函数会调用出错  
  56.     //if (iret) {  
  57.     //  errmsg_ = GetUVError(iret);  
  58.     //  return false;  
  59.     //}  
  60.     return true;  
  61. }  
  62.   
  63. void TCPServer::close()  
  64. {  
  65.     for (auto it = clients_list_.begin(); it!=clients_list_.end(); ++it) {  
  66.         auto data = it->second;  
  67.         uv_close((uv_handle_t*)data->client_handle,AfterClientClose);  
  68.     }  
  69.     clients_list_.clear();  
  70.   
  71.     LOGI("close server");  
  72.     if (isinit_) {  
  73.         uv_close((uv_handle_t*) &server_, AfterServerClose);  
  74.         LOGI("close server");  
  75.     }  
  76.     isinit_ = false;  
  77.     uv_mutex_destroy(&mutex_handle_);  
  78. }  
  79.   
  80. bool TCPServer::run(int status)  
  81. {  
  82.     LOGI("server runing.");  
  83.     int iret = uv_run(loop_,(uv_run_mode)status);  
  84.     if (iret) {  
  85.         errmsg_ = GetUVError(iret);  
  86.         LOGE(errmsg_);  
  87.         return false;  
  88.     }  
  89.     return true;  
  90. }  
  91. //属性设置--服务器与客户端一致  
  92. bool TCPServer::setNoDelay(bool enable)  
  93. {  
  94.     int iret = uv_tcp_nodelay(&server_, enable ? 1 : 0);  
  95.     if (iret) {  
  96.         errmsg_ = GetUVError(iret);  
  97.         LOGE(errmsg_);  
  98.         return false;  
  99.     }  
  100.     return true;  
  101. }  
  102.   
  103. bool TCPServer::setKeepAlive(int enable, unsigned int delay)  
  104. {  
  105.     int iret = uv_tcp_keepalive(&server_, enable , delay);  
  106.     if (iret) {  
  107.         errmsg_ = GetUVError(iret);  
  108.         LOGE(errmsg_);  
  109.         return false;  
  110.     }  
  111.     return true;  
  112. }  
  113.   
  114. //作为server时的函数  
  115. bool TCPServer::bind(const char* ip, int port)  
  116. {  
  117.     struct sockaddr_in bind_addr;  
  118.     int iret = uv_ip4_addr(ip, port, &bind_addr);  
  119.     if (iret) {  
  120.         errmsg_ = GetUVError(iret);  
  121.         LOGE(errmsg_);  
  122.         return false;  
  123.     }  
  124.     iret = uv_tcp_bind(&server_, (const struct sockaddr*)&bind_addr,0);  
  125.     if (iret) {  
  126.         errmsg_ = GetUVError(iret);  
  127.         LOGE(errmsg_);  
  128.         return false;  
  129.     }  
  130.     LOGI("server bind ip="<<ip<<", port="<<port);  
  131.     return true;  
  132. }  
  133.   
  134. bool TCPServer::bind6(const char* ip, int port)  
  135. {  
  136.     struct sockaddr_in6 bind_addr;  
  137.     int iret = uv_ip6_addr(ip, port, &bind_addr);  
  138.     if (iret) {  
  139.         errmsg_ = GetUVError(iret);  
  140.         LOGE(errmsg_);  
  141.         return false;  
  142.     }  
  143.     iret = uv_tcp_bind(&server_, (const struct sockaddr*)&bind_addr,0);  
  144.     if (iret) {  
  145.         errmsg_ = GetUVError(iret);  
  146.         LOGE(errmsg_);  
  147.         return false;  
  148.     }  
  149.     LOGI("server bind ip="<<ip<<", port="<<port);  
  150.     return true;  
  151. }  
  152.   
  153. bool TCPServer::listen(int backlog)  
  154. {  
  155.     int iret = uv_listen((uv_stream_t*) &server_, backlog, acceptConnection);  
  156.     if (iret) {  
  157.         errmsg_ = GetUVError(iret);  
  158.         LOGE(errmsg_);  
  159.         return false;  
  160.     }  
  161.     LOGI("server listen");  
  162.     return true;  
  163. }  
  164.   
  165. bool TCPServer::Start( const char *ip, int port )  
  166. {  
  167.     close();  
  168.     if (!init()) {  
  169.         return false;  
  170.     }  
  171.     if (!bind(ip,port)) {  
  172.         return false;  
  173.     }  
  174.     if (!listen(SOMAXCONN)) {  
  175.         return false;  
  176.     }  
  177.     if (!run()) {  
  178.         return false;  
  179.     }  
  180.     LOGI("start listen "<<ip<<": "<<port);  
  181.     return true;  
  182. }  
  183.   
  184. bool TCPServer::Start6( const char *ip, int port )  
  185. {  
  186.     close();  
  187.     if (!init()) {  
  188.         return false;  
  189.     }  
  190.     if (!bind6(ip,port)) {  
  191.         return false;  
  192.     }  
  193.     if (!listen(SOMAXCONN)) {  
  194.         return false;  
  195.     }  
  196.     if (!run()) {  
  197.         return false;  
  198.     }  
  199.     return true;  
  200. }  
  201.   
  202. //服务器发送函数  
  203. int TCPServer::send(int clientid, const char* data, std::size_t len)  
  204. {  
  205.     auto itfind = clients_list_.find(clientid);  
  206.     if (itfind == clients_list_.end()) {  
  207.         errmsg_ = "can't find cliendid ";  
  208.         errmsg_ += std::to_string((long long)clientid);  
  209.         LOGE(errmsg_);  
  210.         return -1;  
  211.     }  
  212.     //自己控制data的生命周期直到write结束  
  213.     if (itfind->second->writebuffer.len < len) {  
  214.         itfind->second->writebuffer.base = (char*)realloc(itfind->second->writebuffer.base,len);  
  215.         itfind->second->writebuffer.len = len;  
  216.     }  
  217.     memcpy(itfind->second->writebuffer.base,data,len);  
  218.     uv_buf_t buf = uv_buf_init((char*)itfind->second->writebuffer.base,len);  
  219.     int iret = uv_write(&itfind->second->write_req, (uv_stream_t*)itfind->second->client_handle, &buf, 1, AfterSend);  
  220.     if (iret) {  
  221.         errmsg_ = GetUVError(iret);  
  222.         LOGE(errmsg_);  
  223.         return false;  
  224.     }  
  225.     return true;  
  226. }  
  227.   
  228. //服务器-新客户端函数  
  229. void TCPServer::acceptConnection(uv_stream_t *server, int status)  
  230. {  
  231.     if (!server->data) {  
  232.         return;  
  233.     }  
  234.     TCPServer *tcpsock = (TCPServer *)server->data;  
  235.     int clientid = tcpsock->GetAvailaClientID();  
  236.     clientdata* cdata = new clientdata(clientid);//uv_close回调函数中释放  
  237.     cdata->tcp_server = tcpsock;//保存服务器的信息  
  238.     int iret = uv_tcp_init(tcpsock->loop_, cdata->client_handle);//析构函数释放  
  239.     if (iret) {  
  240.         delete cdata;  
  241.         tcpsock->errmsg_ = GetUVError(iret);  
  242.         LOGE(tcpsock->errmsg_);  
  243.         return;  
  244.     }  
  245.     iret = uv_accept((uv_stream_t*)&tcpsock->server_, (uv_stream_t*) cdata->client_handle);  
  246.     if ( iret) {  
  247.         tcpsock->errmsg_ = GetUVError(iret);  
  248.         uv_close((uv_handle_t*) cdata->client_handle, NULL);  
  249.         delete cdata;  
  250.         LOGE(tcpsock->errmsg_);  
  251.         return;  
  252.     }  
  253.     tcpsock->clients_list_.insert(std::make_pair(clientid,cdata));//加入到链接队列  
  254.     if (tcpsock->newconcb_) {  
  255.         tcpsock->newconcb_(clientid);  
  256.     }  
  257.     LOGI("new client("<<cdata->client_handle<<") id="<< clientid);  
  258.     iret = uv_read_start((uv_stream_t*)cdata->client_handle, onAllocBuffer, AfterServerRecv);//服务器开始接收客户端的数据  
  259.     return;  
  260. }  
  261.   
  262. //服务器-接收数据回调函数  
  263. void TCPServer::setrecvcb(int clientid, server_recvcb cb )  
  264. {  
  265.     auto itfind = clients_list_.find(clientid);  
  266.     if (itfind != clients_list_.end()) {  
  267.         itfind->second->recvcb_ = cb;  
  268.     }  
  269. }  
  270.   
  271. //服务器-新链接回调函数  
  272. void TCPServer::setnewconnectcb(newconnect cb )  
  273. {  
  274.     newconcb_ = cb;  
  275. }  
  276.   
  277. //服务器分析空间函数  
  278. void TCPServer::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)  
  279. {  
  280.     if (!handle->data) {  
  281.         return;  
  282.     }  
  283.     clientdata *client = (clientdata*)handle->data;  
  284.     *buf = client->readbuffer;  
  285. }  
  286.   
  287. void TCPServer::AfterServerRecv(uv_stream_t *handle, ssize_t nread, const uv_buf_t* buf)  
  288. {  
  289.     if (!handle->data) {  
  290.         return;  
  291.     }  
  292.     clientdata *client = (clientdata*)handle->data;//服务器的recv带的是clientdata  
  293.     if (nread < 0) {/* Error or EOF */  
  294.         TCPServer *server = (TCPServer *)client->tcp_server;  
  295.         if (nread == UV_EOF) {  
  296.             fprintf(stdout,"客户端(%d)连接断开,关闭此客户端\n",client->client_id);  
  297.             LOGW("客户端("<<client->client_id<<")主动断开");  
  298.         } else if (nread == UV_ECONNRESET) {  
  299.             fprintf(stdout,"客户端(%d)异常断开\n",client->client_id);  
  300.             LOGW("客户端("<<client->client_id<<")异常断开");  
  301.         } else {  
  302.             fprintf(stdout,"%s\n",GetUVError(nread));  
  303.             LOGW("客户端("<<client->client_id<<")异常断开:"<<GetUVError(nread));  
  304.         }  
  305.         server->DeleteClient(client->client_id);//连接断开,关闭客户端  
  306.         return;  
  307.     } else if (0 == nread)  {/* Everything OK, but nothing read. */  
  308.   
  309.     } else if (client->recvcb_) {  
  310.         client->recvcb_(client->client_id,buf->base,nread);  
  311.     }  
  312. }  
  313.   
  314. //服务器与客户端一致  
  315. void TCPServer::AfterSend(uv_write_t *req, int status)  
  316. {  
  317.     if (status < 0) {  
  318.         LOGE("发送数据有误:"<<GetUVError(status));  
  319.         fprintf(stderr, "Write error %s\n", GetUVError(status));  
  320.     }  
  321. }  
  322.   
  323. void TCPServer::AfterServerClose(uv_handle_t *handle)  
  324. {  
  325.     //服务器,不需要做什么  
  326. }  
  327.   
  328. void TCPServer::AfterClientClose(uv_handle_t *handle)  
  329. {  
  330.     clientdata *cdata = (clientdata*)handle->data;  
  331.     LOGI("client "<<cdata->client_id<<" had closed.");  
  332.     delete cdata;  
  333. }  
  334.   
  335. int TCPServer::GetAvailaClientID() const  
  336. {  
  337.     static int s_id = 0;  
  338.     return ++s_id;  
  339. }  
  340.   
  341. bool TCPServer::DeleteClient( int clientid )  
  342. {  
  343.     uv_mutex_lock(&mutex_handle_);  
  344.     auto itfind = clients_list_.find(clientid);  
  345.     if (itfind == clients_list_.end()) {  
  346.         errmsg_ = "can't find client ";  
  347.         errmsg_ += std::to_string((long long)clientid);  
  348.         LOGE(errmsg_);  
  349.         uv_mutex_unlock(&mutex_handle_);  
  350.         return false;  
  351.     }  
  352.     if (uv_is_active((uv_handle_t*)itfind->second->client_handle)) {  
  353.         uv_read_stop((uv_stream_t*)itfind->second->client_handle);  
  354.     }  
  355.     uv_close((uv_handle_t*)itfind->second->client_handle,AfterClientClose);  
  356.   
  357.     clients_list_.erase(itfind);  
  358.     LOGI("删除客户端"<<clientid);  
  359.     uv_mutex_unlock(&mutex_handle_);  
  360.     return true;  
  361. }  
  362.   
  363.   
  364. void TCPServer::StartLog( const char* logpath /*= nullptr*/ )  
  365. {  
  366.     zsummer::log4z::ILog4zManager::GetInstance()->SetLoggerMonthdir(LOG4Z_MAIN_LOGGER_ID, true);  
  367.     zsummer::log4z::ILog4zManager::GetInstance()->SetLoggerDisplay(LOG4Z_MAIN_LOGGER_ID,false);  
  368.     zsummer::log4z::ILog4zManager::GetInstance()->SetLoggerLevel(LOG4Z_MAIN_LOGGER_ID,LOG_LEVEL_DEBUG);  
  369.     zsummer::log4z::ILog4zManager::GetInstance()->SetLoggerLimitSize(LOG4Z_MAIN_LOGGER_ID,100);  
  370.     if (logpath) {  
  371.         zsummer::log4z::ILog4zManager::GetInstance()->SetLoggerPath(LOG4Z_MAIN_LOGGER_ID,logpath);  
  372.     }  
  373.     zsummer::log4z::ILog4zManager::GetInstance()->Start();  
  374. }  
  375.   
  376.   
  377. /*****************************************TCP Client*************************************************************/  
  378. TCPClient::TCPClient(uv_loop_t* loop)  
  379.     :recvcb_(nullptr),userdata_(nullptr)  
  380.     ,connectstatus_(CONNECT_DIS)  
  381.     , isinit_(false)  
  382. {  
  383.     readbuffer_ = uv_buf_init((char*) malloc(BUFFERSIZE), BUFFERSIZE);  
  384.     writebuffer_ = uv_buf_init((char*) malloc(BUFFERSIZE), BUFFERSIZE);  
  385.     loop_ = loop;  
  386.     connect_req_.data = this;  
  387.     write_req_.data = this;  
  388. }  
  389.   
  390.   
  391. TCPClient::~TCPClient()  
  392. {  
  393.     free(readbuffer_.base);  
  394.     readbuffer_.base = nullptr;  
  395.     readbuffer_.len = 0;  
  396.     free(writebuffer_.base);  
  397.     writebuffer_.base = nullptr;  
  398.     writebuffer_.len = 0;  
  399.     close();  
  400.     LOGI("客户端("<<this<<")退出");  
  401. }  
  402. //初始化与关闭--服务器与客户端一致  
  403. bool TCPClient::init()  
  404. {  
  405.     if (isinit_) {  
  406.         return true;  
  407.     }  
  408.   
  409.     if (!loop_) {  
  410.         errmsg_ = "loop is null on tcp init.";  
  411.         LOGE(errmsg_);  
  412.         return false;  
  413.     }  
  414.     int iret = uv_tcp_init(loop_,&client_);  
  415.     if (iret) {  
  416.         errmsg_ = GetUVError(iret);  
  417.         LOGE(errmsg_);  
  418.         return false;  
  419.     }  
  420.     iret = uv_mutex_init(&write_mutex_handle_);  
  421.     if (iret) {  
  422.         errmsg_ = GetUVError(iret);  
  423.         LOGE(errmsg_);  
  424.         return false;  
  425.     }  
  426.     isinit_ = true;  
  427.     fprintf(stdout,"客户端(%p) init type = %d\n",&client_,client_.type);  
  428.     client_.data = this;  
  429.     //iret = uv_tcp_keepalive(&client_, 1, 60);//  
  430.     //if (iret) {  
  431.     //    errmsg_ = GetUVError(iret);  
  432.     //    return false;  
  433.     //}  
  434.     LOGI("客户端("<<this<<")Init");  
  435.     return true;  
  436. }  
  437.   
  438. void TCPClient::close()  
  439. {  
  440.     if (!isinit_) {  
  441.         return;  
  442.     }  
  443.     uv_mutex_destroy(&write_mutex_handle_);  
  444.     uv_close((uv_handle_t*) &client_, AfterClose);  
  445.     LOGI("客户端("<<this<<")close");  
  446.     isinit_ = false;  
  447. }  
  448.   
  449. bool TCPClient::run(int status)  
  450. {  
  451.     LOGI("客户端("<<this<<")run");  
  452.     int iret = uv_run(loop_,(uv_run_mode)status);  
  453.     if (iret) {  
  454.         errmsg_ = GetUVError(iret);  
  455.         LOGE(errmsg_);  
  456.         return false;  
  457.     }  
  458.     return true;  
  459. }  
  460.   
  461. //属性设置--服务器与客户端一致  
  462. bool TCPClient::setNoDelay(bool enable)  
  463. {  
  464.     //http://blog.csdn.net/u011133100/article/details/21485983  
  465.     int iret = uv_tcp_nodelay(&client_, enable ? 1 : 0);  
  466.     if (iret) {  
  467.         errmsg_ = GetUVError(iret);  
  468.         LOGE(errmsg_);  
  469.         return false;  
  470.     }  
  471.     return true;  
  472. }  
  473.   
  474. bool TCPClient::setKeepAlive(int enable, unsigned int delay)  
  475. {  
  476.     int iret = uv_tcp_keepalive(&client_, enable , delay);  
  477.     if (iret) {  
  478.         errmsg_ = GetUVError(iret);  
  479.         LOGE(errmsg_);  
  480.         return false;  
  481.     }  
  482.     return true;  
  483. }  
  484.   
  485. //作为client的connect函数  
  486. bool TCPClient::connect(const char* ip, int port)  
  487. {  
  488.     close();  
  489.     init();  
  490.     connectip_ = ip;  
  491.     connectport_ = port;  
  492.     LOGI("客户端("<<this<<")start connect to server("<<ip<<":"<<port<<")");  
  493.     int iret = uv_thread_create(&connect_threadhanlde_, ConnectThread, this);//触发AfterConnect才算真正连接成功,所以用线程  
  494.     if (iret) {  
  495.         errmsg_ = GetUVError(iret);  
  496.         LOGE(errmsg_);  
  497.         return false;  
  498.     }  
  499.     while ( connectstatus_ == CONNECT_DIS) {  
  500. #if defined (WIN32) || defined(_WIN32)  
  501.         Sleep(100);  
  502. #else  
  503.         usleep((100) * 1000)  
  504. #endif  
  505.     }  
  506.     return connectstatus_ == CONNECT_FINISH;  
  507. }  
  508.   
  509. bool TCPClient::connect6(const char* ip, int port)  
  510. {  
  511.     close();  
  512.     init();  
  513.     connectip_ = ip;  
  514.     connectport_ = port;  
  515.     LOGI("客户端("<<this<<")start connect to server("<<ip<<":"<<port<<")");  
  516.     int iret = uv_thread_create(&connect_threadhanlde_, ConnectThread6, this);//触发AfterConnect才算真正连接成功,所以用线程  
  517.     if (iret) {  
  518.         errmsg_ = GetUVError(iret);  
  519.         LOGE(errmsg_);  
  520.         return false;  
  521.     }  
  522.     while ( connectstatus_ == CONNECT_DIS) {  
  523.         //fprintf(stdout,"client(%p) wait, connect status %d\n",this,connectstatus_);  
  524. #if defined (WIN32) || defined(_WIN32)  
  525.         Sleep(100);  
  526. #else  
  527.         usleep((100) * 1000)  
  528. #endif  
  529.     }  
  530.     return connectstatus_ == CONNECT_FINISH;  
  531. }  
  532.   
  533. void TCPClient::ConnectThread( void* arg )  
  534. {  
  535.     TCPClient *pclient = (TCPClient*)arg;  
  536.     fprintf(stdout,"client(%p) ConnectThread start\n",pclient);  
  537.     struct sockaddr_in bind_addr;  
  538.     int iret = uv_ip4_addr(pclient->connectip_.c_str(), pclient->connectport_, &bind_addr);  
  539.     if (iret) {  
  540.         pclient->errmsg_ = GetUVError(iret);  
  541.         LOGE(pclient->errmsg_);  
  542.         return;  
  543.     }  
  544.     iret = uv_tcp_connect(&pclient->connect_req_, &pclient->client_, (const sockaddr*)&bind_addr, AfterConnect);  
  545.     if (iret) {  
  546.         pclient->errmsg_ = GetUVError(iret);  
  547.         LOGE(pclient->errmsg_);  
  548.         return;  
  549.     }  
  550.     fprintf(stdout,"client(%p) ConnectThread end, connect status %d\n",pclient, pclient->connectstatus_);  
  551.     pclient->run();  
  552. }  
  553.   
  554.   
  555. void TCPClient::ConnectThread6( void* arg )  
  556. {  
  557.     TCPClient *pclient = (TCPClient*)arg;  
  558.     LOGI("客户端("<<pclient<<")Enter Connect Thread.");  
  559.     fprintf(stdout,"client(%p) ConnectThread start\n",pclient);  
  560.     struct sockaddr_in6 bind_addr;  
  561.     int iret = uv_ip6_addr(pclient->connectip_.c_str(), pclient->connectport_, &bind_addr);  
  562.     if (iret) {  
  563.         pclient->errmsg_ = GetUVError(iret);  
  564.         LOGE(pclient->errmsg_);  
  565.         return;  
  566.     }  
  567.     iret = uv_tcp_connect(&pclient->connect_req_, &pclient->client_, (const sockaddr*)&bind_addr, AfterConnect);  
  568.     if (iret) {  
  569.         pclient->errmsg_ = GetUVError(iret);  
  570.         LOGE(pclient->errmsg_);  
  571.         return;  
  572.     }  
  573.     fprintf(stdout,"client(%p) ConnectThread end, connect status %d\n",pclient, pclient->connectstatus_);  
  574.     LOGI("客户端("<<pclient<<")Leave Connect Thread. connect status "<<pclient->connectstatus_);  
  575.     pclient->run();  
  576. }  
  577.   
  578. void TCPClient::AfterConnect(uv_connect_t* handle, int status)  
  579. {  
  580.     fprintf(stdout,"start after connect\n");  
  581.     TCPClient *pclient = (TCPClient*)handle->handle->data;  
  582.     if (status) {  
  583.         pclient->connectstatus_ = CONNECT_ERROR;  
  584.         fprintf(stdout,"connect error:%s\n",GetUVError(status));  
  585.         return;  
  586.     }  
  587.   
  588.     int iret = uv_read_start(handle->handle, onAllocBuffer, AfterClientRecv);//客户端开始接收服务器的数据  
  589.     if (iret) {  
  590.         fprintf(stdout,"uv_read_start error:%s\n",GetUVError(iret));  
  591.         pclient->connectstatus_ = CONNECT_ERROR;  
  592.     } else {  
  593.         pclient->connectstatus_ = CONNECT_FINISH;  
  594.     }  
  595.     LOGI("客户端("<<pclient<<")run");  
  596.     fprintf(stdout,"end after connect\n");  
  597. }  
  598.   
  599. //客户端的发送函数  
  600. int TCPClient::send(const char* data, std::size_t len)  
  601. {  
  602.     //自己控制data的生命周期直到write结束  
  603.     if (!data || len <= 0) {  
  604.         errmsg_ = "send data is null or len less than zero.";  
  605.         return 0;  
  606.     }  
  607.   
  608.     uv_mutex_lock(&write_mutex_handle_);  
  609.     if (writebuffer_.len < len) {  
  610.         writebuffer_.base = (char*)realloc(writebuffer_.base,len);  
  611.         writebuffer_.len = len;  
  612.     }  
  613.     memcpy(writebuffer_.base,data,len);  
  614.     uv_buf_t buf = uv_buf_init((char*)writebuffer_.base,len);  
  615.     int iret = uv_write(&write_req_, (uv_stream_t*)&client_, &buf, 1, AfterSend);  
  616.     if (iret) {  
  617.         uv_mutex_unlock(&write_mutex_handle_);  
  618.         errmsg_ = GetUVError(iret);  
  619.         LOGE(errmsg_);  
  620.         return false;  
  621.     }  
  622.     return true;  
  623. }  
  624.   
  625. //客户端-接收数据回调函数  
  626. void TCPClient::setrecvcb(client_recvcb cb, void* userdata )  
  627. {  
  628.     recvcb_ = cb;  
  629.     userdata_ = userdata;  
  630. }  
  631.   
  632. //客户端分析空间函数  
  633. void TCPClient::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)  
  634. {  
  635.     if (!handle->data) {  
  636.         return;  
  637.     }  
  638.     TCPClient *client = (TCPClient*)handle->data;  
  639.     *buf = client->readbuffer_;  
  640. }  
  641.   
  642.   
  643. void TCPClient::AfterClientRecv(uv_stream_t *handle, ssize_t nread, const uv_buf_t* buf)  
  644. {  
  645.     if (!handle->data) {  
  646.         return;  
  647.     }  
  648.     TCPClient *client = (TCPClient*)handle->data;//服务器的recv带的是TCPClient  
  649.     if (nread < 0) {  
  650.         if (nread == UV_EOF) {  
  651.             fprintf(stdout,"服务器(%p)主动断开\n",handle);  
  652.             LOGW("服务器主动断开");  
  653.         } else if (nread == UV_ECONNRESET) {  
  654.             fprintf(stdout,"服务器(%p)异常断开\n",handle);  
  655.             LOGW("服务器异常断开");  
  656.         } else {  
  657.             fprintf(stdout,"服务器(%p)异常断开:%s\n",handle,GetUVError(nread));  
  658.             LOGW("服务器异常断开"<<GetUVError(nread));  
  659.         }  
  660.         uv_close((uv_handle_t*)handle, AfterClose);  
  661.         return;  
  662.     }  
  663.     if (nread > 0 && client->recvcb_) {  
  664.         client->recvcb_(buf->base,nread,client->userdata_);  
  665.     }  
  666. }  
  667.   
  668. //服务器与客户端一致  
  669. void TCPClient::AfterSend(uv_write_t *req, int status)  
  670. {  
  671.     TCPClient *client = (TCPClient *)req->handle->data;  
  672.     uv_mutex_unlock(&client->write_mutex_handle_);  
  673.     if (status < 0) {  
  674.         LOGE("发送数据有误:"<<GetUVError(status));  
  675.         fprintf(stderr, "Write error %s\n", GetUVError(status));  
  676.     }  
  677. }  
  678. //服务器与客户端一致  
  679. void TCPClient::AfterClose(uv_handle_t *handle)  
  680. {  
  681.     fprintf(stdout,"客户端(%p)已close\n",handle);  
  682.     LOGI("客户端("<<handle<<")已close");  
  683. }  
  684.   
  685. void TCPClient::StartLog( const char* logpath /*= nullptr*/ )  
  686. {  
  687.     zsummer::log4z::ILog4zManager::GetInstance()->SetLoggerMonthdir(LOG4Z_MAIN_LOGGER_ID, true);  
  688.     zsummer::log4z::ILog4zManager::GetInstance()->SetLoggerDisplay(LOG4Z_MAIN_LOGGER_ID,false);  
  689.     zsummer::log4z::ILog4zManager::GetInstance()->SetLoggerLevel(LOG4Z_MAIN_LOGGER_ID,LOG_LEVEL_DEBUG);  
  690.     zsummer::log4z::ILog4zManager::GetInstance()->SetLoggerLimitSize(LOG4Z_MAIN_LOGGER_ID,100);  
  691.     if (logpath) {  
  692.         zsummer::log4z::ILog4zManager::GetInstance()->SetLoggerPath(LOG4Z_MAIN_LOGGER_ID,logpath);  
  693.     }  
  694.     zsummer::log4z::ILog4zManager::GetInstance()->Start();  
  695. }  
  696.   
  697. }  

按照例子,客户端可以并发20多路,超过uv_write就会assert出错,未找到原因

服务器可以接收几十路连接。万百上千路未测试过,因为没有模拟环境。

0 0