platformNetwork.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #include "platformNetwork.h"
  2. /**
  3. * @brief 连接mqtt服务器
  4. *
  5. * @param userData
  6. * @param platformNetwork
  7. * @param host
  8. * @param port
  9. * @return RyanMqttError_e
  10. * 成功返回RyanMqttSuccessError, 失败返回错误信息
  11. */
  12. RyanMqttError_e platformNetworkConnect(void *userData, platformNetwork_t *platformNetwork, const char *host, const char *port)
  13. {
  14. RyanMqttError_e result = RyanMqttSuccessError;
  15. struct addrinfo *addrList = NULL;
  16. struct addrinfo hints = {
  17. .ai_family = AF_UNSPEC, // 指定返回地址的地址族
  18. .ai_socktype = SOCK_STREAM, // 指定返回地址的地址族
  19. .ai_protocol = IPPROTO_IP}; // 指定socket的协议
  20. if (getaddrinfo(host, port, &hints, &addrList) != 0)
  21. {
  22. result = RyanSocketFailedError;
  23. goto exit;
  24. }
  25. if (NULL == addrList)
  26. goto exit;
  27. platformNetwork->socket = socket(addrList->ai_family, addrList->ai_socktype, addrList->ai_protocol);
  28. if (platformNetwork->socket < 0)
  29. {
  30. result = RyanSocketFailedError;
  31. goto exit;
  32. }
  33. if (connect(platformNetwork->socket, addrList->ai_addr, addrList->ai_addrlen) != 0)
  34. {
  35. platformNetworkClose(userData, platformNetwork);
  36. result = RyanMqttSocketConnectFailError;
  37. goto exit;
  38. }
  39. exit:
  40. if (NULL != addrList)
  41. freeaddrinfo(addrList);
  42. return result;
  43. }
  44. /**
  45. * @brief 非阻塞接收数据
  46. *
  47. * @param userData
  48. * @param platformNetwork
  49. * @param recvBuf
  50. * @param recvLen
  51. * @param timeout
  52. * @return RyanMqttError_e
  53. * socket错误返回 RyanSocketFailedError
  54. * 接收超时或者接收数据长度不等于期待数据接受长度 RyanMqttRecvPacketTimeOutError
  55. * 接收成功 RyanMqttSuccessError
  56. */
  57. RyanMqttError_e platformNetworkRecvAsync(void *userData, platformNetwork_t *platformNetwork, char *recvBuf, int recvLen, int timeout)
  58. {
  59. int32_t recvResult = 0;
  60. int32_t offset = 0;
  61. int32_t timeOut2 = timeout;
  62. struct timeval tv = {0};
  63. platformTimer_t timer = {0};
  64. if (-1 == platformNetwork->socket)
  65. return RyanSocketFailedError;
  66. platformTimerCutdown(&timer, timeout);
  67. while ((offset < recvLen) && (0 != timeOut2))
  68. {
  69. tv.tv_sec = timeOut2 / 1000;
  70. tv.tv_usec = timeOut2 % 1000 * 1000;
  71. if (tv.tv_sec <= 0 && tv.tv_usec <= 100)
  72. {
  73. tv.tv_sec = 0;
  74. tv.tv_usec = 100;
  75. }
  76. setsockopt(platformNetwork->socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)); // 设置接收超时
  77. recvResult = recv(platformNetwork->socket, recvBuf, recvLen - offset, 0);
  78. if (recvResult < 0)
  79. {
  80. if ((errno == EAGAIN || // 套接字已标记为非阻塞,而接收操作被阻塞或者接收超时
  81. errno == EWOULDBLOCK || // 发送时套接字发送缓冲区已满,或接收时套接字接收缓冲区为空
  82. errno == EINTR)) // 操作被信号中断
  83. break;
  84. return RyanSocketFailedError;
  85. }
  86. offset += recvResult;
  87. timeOut2 = platformTimerRemain(&timer);
  88. }
  89. if (offset != recvLen)
  90. return RyanMqttRecvPacketTimeOutError;
  91. return RyanMqttSuccessError;
  92. }
  93. /**
  94. * @brief 非阻塞发送数据
  95. *
  96. * @param userData
  97. * @param platformNetwork
  98. * @param sendBuf
  99. * @param sendLen
  100. * @param timeout
  101. * @return RyanMqttError_e
  102. * socket错误返回 RyanSocketFailedError
  103. * 接收超时或者接收数据长度不等于期待数据接受长度 RyanMqttRecvPacketTimeOutError
  104. * 接收成功 RyanMqttSuccessError
  105. */
  106. RyanMqttError_e platformNetworkSendAsync(void *userData, platformNetwork_t *platformNetwork, char *sendBuf, int sendLen, int timeout)
  107. {
  108. int32_t sendResult = 0;
  109. int32_t offset = 0;
  110. int32_t timeOut2 = timeout;
  111. struct timeval tv = {0};
  112. platformTimer_t timer = {0};
  113. if (-1 == platformNetwork->socket)
  114. return RyanSocketFailedError;
  115. platformTimerCutdown(&timer, timeout);
  116. while ((offset < sendLen) && (0 != timeOut2))
  117. {
  118. tv.tv_sec = timeOut2 / 1000;
  119. tv.tv_usec = timeOut2 % 1000 * 1000;
  120. if (tv.tv_sec <= 0 && tv.tv_usec <= 100)
  121. {
  122. tv.tv_sec = 0;
  123. tv.tv_usec = 100;
  124. }
  125. setsockopt(platformNetwork->socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(struct timeval)); // 设置发送超时
  126. sendResult = send(platformNetwork->socket, sendBuf, sendLen - offset, 0);
  127. if (sendResult < 0)
  128. {
  129. if ((errno == EAGAIN || // 套接字已标记为非阻塞,而接收操作被阻塞或者接收超时
  130. errno == EWOULDBLOCK || // 发送时套接字发送缓冲区已满,或接收时套接字接收缓冲区为空
  131. errno == EINTR)) // 操作被信号中断
  132. break;
  133. return RyanSocketFailedError;
  134. }
  135. offset += sendResult;
  136. timeOut2 = platformTimerRemain(&timer);
  137. }
  138. if (offset != sendLen)
  139. return RyanMqttSendPacketTimeOutError;
  140. return RyanMqttSuccessError;
  141. }
  142. /**
  143. * @brief 断开mqtt服务器连接
  144. *
  145. * @param userData
  146. * @param platformNetwork
  147. * @return RyanMqttError_e
  148. */
  149. RyanMqttError_e platformNetworkClose(void *userData, platformNetwork_t *platformNetwork)
  150. {
  151. if (platformNetwork->socket >= 0)
  152. {
  153. closesocket(platformNetwork->socket);
  154. platformNetwork->socket = -1;
  155. }
  156. return RyanMqttSuccessError;
  157. }