分享

libuv在windows的简单使用

 15所 2020-09-18

libuv的官网:http:///

关于libuv的介绍网上都有,大家可以去搜一下。

而如何在windows上安装libuv,我这边是使用vcpkg安装的,学习的时候极力推荐使用这种方式安装,关于vcpkg的使用可以参考这篇博客:https://blog.csdn.net/cjmqas/article/details/79282847

libuv底层在windows使用的是IOCP机制,IOCP是个神器,但是学起来是真的难,学好了,用起来也就容易了,但是学好谈何容易。关于IOCP的介绍可以看这篇博客:https://blog.csdn.net/piggyxp/article/details/6922277

综上所述,我就想在windows下试试使用libuv编写一个简单的服务器软件来测试测试libuv的性能,代码如下:

  1. #include <iostream>
  2. #include <uv.h>
  3. #include <uv/errno.h>
  4. #include <spdlog/spdlog.h>
  5. // 客户端关闭socket时回调函数
  6. void OnClose(uv_handle_t* handle)
  7. {
  8. free(handle);
  9. }
  10. // 接收socket数据前分配缓冲区函数回调函数
  11. void ClientAlloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
  12. {
  13. buf->base = reinterpret_cast<char*>(malloc(suggested_size));
  14. buf->len = suggested_size;
  15. }
  16. //
  17. void ClientRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf)
  18. {
  19. sockaddr_in streamAddr;
  20. int nameLen = sizeof(sockaddr_in);
  21. // 当数据大于0时为接收数据,小于0时是客户端断开连接
  22. if (nread > 0)
  23. {
  24. char szIpAdderss[17] = { 0, };
  25. uv_tcp_getpeername(reinterpret_cast<uv_tcp_t*>(stream), reinterpret_cast<sockaddr*>(&streamAddr), &nameLen);
  26. uv_ip4_name(&streamAddr, szIpAdderss, 17);
  27. buf->base[nread] = '\0';
  28. spdlog::info('ip {0}, port {1}, data length {2}, data {3}', szIpAdderss, ntohs(streamAddr.sin_port), nread, buf->base);
  29. }
  30. else if (nread < 0)
  31. {
  32. if (nread != UV_EOF)
  33. {
  34. spdlog::error('ClientRead fail, {0}', uv_strerror(nread));
  35. }
  36. else
  37. {
  38. sockaddr_in streamAddr;
  39. int nameLen = sizeof(sockaddr_in);
  40. char szIpAdderss[17] = { 0, };
  41. uv_tcp_getpeername(reinterpret_cast<uv_tcp_t*>(stream), reinterpret_cast<sockaddr*>(&streamAddr), &nameLen);
  42. uv_ip4_name(&streamAddr, szIpAdderss, 17);
  43. spdlog::info('ip {0}, port {1} disconnect', szIpAdderss, ntohs(streamAddr.sin_port));
  44. // 注册断开连接回调函数
  45. uv_close(reinterpret_cast<uv_handle_t*>(stream), OnClose);
  46. }
  47. }
  48. free(buf->base);
  49. }
  50. // 监听回调函数
  51. void OnConnect(uv_stream_t* server, int status)
  52. {
  53. if (status == -1)
  54. {
  55. return;
  56. }
  57. // 分配客户端对象
  58. uv_tcp_t *pClient = reinterpret_cast<uv_tcp_t*>(malloc(sizeof(uv_tcp_t)));
  59. // 为客户端对象绑定libuv循环
  60. int retValue = uv_tcp_init(uv_default_loop(), pClient);;
  61. if (retValue != 0)
  62. {
  63. spdlog::error('uv_tcp_init fail, {0}', uv_strerror(retValue));
  64. uv_close(reinterpret_cast<uv_handle_t*>(pClient), OnClose);
  65. }
  66. else
  67. {
  68. // 接收客户端连接
  69. int retValue = uv_accept(server, reinterpret_cast<uv_stream_t*>(pClient));
  70. if (retValue != 0)
  71. {
  72. spdlog::error('uv_accept fail, {0}', uv_strerror(retValue));
  73. uv_close(reinterpret_cast<uv_handle_t*>(pClient), OnClose);
  74. }
  75. else
  76. {
  77. // 绑定客户端读分配内存和读回调函数
  78. uv_read_start(reinterpret_cast<uv_stream_t*>(pClient), ClientAlloc, ClientRead);
  79. }
  80. }
  81. }
  82. int main()
  83. {
  84. // 初始化libuv循环
  85. auto pLoop = uv_default_loop();
  86. // 初始化libuv服务器
  87. uv_tcp_t server;
  88. uv_tcp_init(pLoop, &server);
  89. sockaddr_in bindAddr;
  90. int retValue = uv_ip4_addr('0.0.0.0', 43000, &bindAddr);
  91. if (retValue != 0)
  92. {
  93. spdlog::error('uv_ip4_addr fail, {0}', uv_strerror(retValue));
  94. return -1;
  95. }
  96. // 绑定地址和端口
  97. retValue = uv_tcp_bind(&server, reinterpret_cast<sockaddr*>(&bindAddr), 0);
  98. if (retValue != 0)
  99. {
  100. spdlog::error('uv_tcp_bind fail, {0}', uv_strerror(retValue));
  101. return -2;
  102. }
  103. // 开始监听
  104. retValue = uv_listen(reinterpret_cast<uv_stream_t*>(&server), 128, OnConnect);
  105. if (retValue != 0)
  106. {
  107. spdlog::error('uv_listen fail, {0}', uv_strerror(retValue));
  108. return -3;
  109. }
  110. // 开启libuv循环
  111. return uv_run(pLoop, UV_RUN_DEFAULT);
  112. }

测试的时候使用的是上面介绍IOCP的博客所提供的客户端,目的是对比使用IOCP写的服务器和使用libuv写的服务器之间的差异,结果看来是没多大差别的。

以上就是本博客的全文,本人限于能力,上文中难免有错误的地方,若读者发现上文的错误,请于评论区中指出,本人看到之后会立即修改的,谢谢。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多