platformNetwork.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. #define rlogEnable 1 // 是否使能日志
  2. #define rlogColorEnable 1 // 是否使能日志颜色
  3. #define rlogLevel (rlogLvlWarning) // 日志打印等级
  4. #define rlogTag "RyanMqttNet" // 日志tag
  5. #include "platformNetwork.h"
  6. #include "RyanMqttLog.h"
  7. /**
  8. * @brief 连接mqtt服务器
  9. *
  10. * @param userData
  11. * @param platformNetwork
  12. * @param host
  13. * @param port
  14. * @return RyanMqttError_e
  15. * 成功返回RyanMqttSuccessError, 失败返回错误信息
  16. */
  17. RyanMqttError_e platformNetworkConnect(void *userData, platformNetwork_t *platformNetwork, const char *host, const char *port)
  18. {
  19. RyanMqttError_e result = RyanMqttSuccessError;
  20. char buf[256];
  21. int ret;
  22. struct hostent hostinfo, *phost;
  23. if (0 != gethostbyname_r(host, &hostinfo, buf, sizeof(buf), &phost, &ret))
  24. {
  25. result = RyanSocketFailedError;
  26. goto exit;
  27. }
  28. platformNetwork->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
  29. if (platformNetwork->socket < 0)
  30. {
  31. result = RyanSocketFailedError;
  32. goto exit;
  33. }
  34. struct sockaddr_in server_addr;
  35. memset(&server_addr, 0, sizeof(server_addr));
  36. server_addr.sin_family = AF_INET;
  37. server_addr.sin_port = htons(atoi(port)); // 指定端口号,这里使用HTTP默认端口80
  38. server_addr.sin_addr = *((struct in_addr *)hostinfo.h_addr_list[0]);
  39. // 绑定套接字到主机地址和端口号
  40. if (connect(platformNetwork->socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0)
  41. {
  42. platformNetworkClose(userData, platformNetwork);
  43. result = RyanMqttSocketConnectFailError;
  44. goto exit;
  45. }
  46. exit:
  47. return result;
  48. }
  49. /**
  50. * @brief 非阻塞接收数据
  51. *
  52. * @param userData
  53. * @param platformNetwork
  54. * @param recvBuf
  55. * @param recvLen
  56. * @param timeout
  57. * @return RyanMqttError_e
  58. * socket错误返回 RyanSocketFailedError
  59. * 接收超时或者接收数据长度不等于期待数据接受长度 RyanMqttRecvPacketTimeOutError
  60. * 接收成功 RyanMqttSuccessError
  61. */
  62. RyanMqttError_e platformNetworkRecvAsync(void *userData, platformNetwork_t *platformNetwork, char *recvBuf, int recvLen, int timeout)
  63. {
  64. int32_t recvResult = 0;
  65. int32_t offset = 0;
  66. int32_t timeOut2 = timeout;
  67. struct timeval tv = {0};
  68. platformTimer_t timer = {0};
  69. if (-1 == platformNetwork->socket)
  70. return RyanSocketFailedError;
  71. platformTimerCutdown(&timer, timeout);
  72. while ((offset < recvLen) && (0 != timeOut2))
  73. {
  74. tv.tv_sec = timeOut2 / 1000;
  75. tv.tv_usec = timeOut2 % 1000 * 1000;
  76. if (tv.tv_sec <= 0 && tv.tv_usec <= 100)
  77. {
  78. tv.tv_sec = 0;
  79. tv.tv_usec = 100;
  80. }
  81. setsockopt(platformNetwork->socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)); // 设置错做模式为非阻塞
  82. recvResult = recv(platformNetwork->socket, recvBuf + offset, recvLen - offset, 0);
  83. if (recvResult <= 0) // 小于零,表示错误,个别错误不代表socket错误
  84. {
  85. // 下列3种表示没问题,但需要推出发送
  86. if ((errno == EAGAIN || // 套接字已标记为非阻塞,而接收操作被阻塞或者接收超时
  87. errno == EWOULDBLOCK || // 发送时套接字发送缓冲区已满,或接收时套接字接收缓冲区为空
  88. errno == EINTR)) // 操作被信号中断
  89. break;
  90. return RyanSocketFailedError;
  91. }
  92. offset += recvResult;
  93. timeOut2 = platformTimerRemain(&timer);
  94. }
  95. if (offset != recvLen)
  96. return RyanMqttRecvPacketTimeOutError;
  97. return RyanMqttSuccessError;
  98. // int32_t recvResult = 0;
  99. // int32_t offset = 0;
  100. // int32_t timeOut2 = timeout;
  101. // struct timeval tv = {0};
  102. // platformTimer_t timer = {0};
  103. // if (-1 == platformNetwork->socket)
  104. // return RyanSocketFailedError;
  105. // platformTimerCutdown(&timer, timeout);
  106. // while ((offset < recvLen) && (0 != timeOut2))
  107. // {
  108. // tv.tv_sec = timeOut2 / 1000;
  109. // tv.tv_usec = timeOut2 % 1000 * 1000;
  110. // if (tv.tv_sec <= 0 && tv.tv_usec <= 100)
  111. // {
  112. // tv.tv_sec = 0;
  113. // tv.tv_usec = 100;
  114. // }
  115. // fd_set readset;
  116. // int i, maxfdp1;
  117. // /* 清空可读事件描述符列表 */
  118. // FD_ZERO(&readset);
  119. // /* 将需要监听可读事件的描述符加入列表 */
  120. // FD_SET(platformNetwork->socket, &readset);
  121. // /* 等待设定的网络描述符有事件发生 */
  122. // i = select(platformNetwork->socket + 1, &readset, RT_NULL, RT_NULL, &tv);
  123. // if (i < 0)
  124. // {
  125. // // 下列3种表示没问题,但需要退出接收
  126. // if ((errno == EAGAIN || // 套接字已标记为非阻塞,而接收操作被阻塞或者接收超时
  127. // errno == EWOULDBLOCK || // 发送时套接字发送缓冲区已满,或接收时套接字接收缓冲区为空
  128. // errno == EINTR)) // 操作被信号中断
  129. // break;
  130. // return RyanSocketFailedError;
  131. // }
  132. // /* 查看 sock 描述符上有没有发生可读事件 */
  133. // if (i > 0 && FD_ISSET(platformNetwork->socket, &readset))
  134. // {
  135. // recvResult = recv(platformNetwork->socket, recvBuf + offset, recvLen - offset, 0);
  136. // if (recvResult <= 0) // 小于零,表示错误,个别错误不代表socket错误
  137. // {
  138. // // 下列3种表示没问题,但需要退出接收
  139. // if ((errno == EAGAIN || // 套接字已标记为非阻塞,而接收操作被阻塞或者接收超时
  140. // errno == EWOULDBLOCK || // 发送时套接字发送缓冲区已满,或接收时套接字接收缓冲区为空
  141. // errno == EINTR)) // 操作被信号中断
  142. // break;
  143. // return RyanSocketFailedError;
  144. // }
  145. // offset += recvResult;
  146. // }
  147. // timeOut2 = platformTimerRemain(&timer);
  148. // }
  149. // if (offset != recvLen)
  150. // return RyanMqttRecvPacketTimeOutError;
  151. // return RyanMqttSuccessError;
  152. }
  153. /**
  154. * @brief 非阻塞发送数据
  155. *
  156. * @param userData
  157. * @param platformNetwork
  158. * @param sendBuf
  159. * @param sendLen
  160. * @param timeout
  161. * @return RyanMqttError_e
  162. * socket错误返回 RyanSocketFailedError
  163. * 接收超时或者接收数据长度不等于期待数据接受长度 RyanMqttRecvPacketTimeOutError
  164. * 接收成功 RyanMqttSuccessError
  165. */
  166. RyanMqttError_e platformNetworkSendAsync(void *userData, platformNetwork_t *platformNetwork, char *sendBuf, int sendLen, int timeout)
  167. {
  168. int32_t sendResult = 0;
  169. int32_t offset = 0;
  170. int32_t timeOut2 = timeout;
  171. struct timeval tv = {0};
  172. platformTimer_t timer = {0};
  173. if (-1 == platformNetwork->socket)
  174. return RyanSocketFailedError;
  175. platformTimerCutdown(&timer, timeout);
  176. while ((offset < sendLen) && (0 != timeOut2))
  177. {
  178. tv.tv_sec = timeOut2 / 1000;
  179. tv.tv_usec = timeOut2 % 1000 * 1000;
  180. if (tv.tv_sec <= 0 && tv.tv_usec <= 100)
  181. {
  182. tv.tv_sec = 0;
  183. tv.tv_usec = 100;
  184. }
  185. setsockopt(platformNetwork->socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(struct timeval)); // 设置错做模式为非阻塞
  186. sendResult = send(platformNetwork->socket, sendBuf + offset, sendLen - offset, 0);
  187. if (sendResult <= 0) // 小于零,表示错误,个别错误不代表socket错误
  188. {
  189. // 下列3种表示没问题,但需要推出发送
  190. if ((errno == EAGAIN || // 套接字已标记为非阻塞,而接收操作被阻塞或者接收超时
  191. errno == EWOULDBLOCK || // 发送时套接字发送缓冲区已满,或接收时套接字接收缓冲区为空
  192. errno == EINTR)) // 操作被信号中断
  193. break;
  194. return RyanSocketFailedError;
  195. }
  196. offset += sendResult;
  197. timeOut2 = platformTimerRemain(&timer);
  198. }
  199. if (offset != sendLen)
  200. return RyanMqttSendPacketTimeOutError;
  201. return RyanMqttSuccessError;
  202. }
  203. /**
  204. * @brief 断开mqtt服务器连接
  205. *
  206. * @param userData
  207. * @param platformNetwork
  208. * @return RyanMqttError_e
  209. */
  210. RyanMqttError_e platformNetworkClose(void *userData, platformNetwork_t *platformNetwork)
  211. {
  212. if (platformNetwork->socket >= 0)
  213. {
  214. closesocket(platformNetwork->socket);
  215. platformNetwork->socket = -1;
  216. }
  217. return RyanMqttSuccessError;
  218. }