|
|
@@ -1,11 +1,37 @@
|
|
|
-// #define rlogEnable // 是否使能日志
|
|
|
-#define rlogColorEnable // 是否使能日志颜色
|
|
|
-#define rlogLevel (rlogLvlWarning) // 日志打印等级
|
|
|
-#define rlogTag "RyanMqttNet" // 日志tag
|
|
|
+#define rlogEnable // 是否使能日志
|
|
|
+#define rlogColorEnable // 是否使能日志颜色
|
|
|
+#define rlogLevel (rlogLvlDebug) // 日志打印等级
|
|
|
+#define rlogTag "RyanMqttNet" // 日志tag
|
|
|
|
|
|
#include "platformNetwork.h"
|
|
|
#include "RyanMqttLog.h"
|
|
|
|
|
|
+/**
|
|
|
+ * @brief 初始化网络接口层
|
|
|
+ *
|
|
|
+ * @param userData
|
|
|
+ * @param platformNetwork
|
|
|
+ * @return RyanMqttError_e
|
|
|
+ */
|
|
|
+RyanMqttError_e platformNetworkInit(void *userData, platformNetwork_t *platformNetwork)
|
|
|
+{
|
|
|
+ platformNetwork->socket = -1;
|
|
|
+ return RyanMqttSuccessError;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 销毁网络接口层
|
|
|
+ *
|
|
|
+ * @param userData
|
|
|
+ * @param platformNetwork
|
|
|
+ * @return RyanMqttError_e
|
|
|
+ */
|
|
|
+RyanMqttError_e platformNetworkDestroy(void *userData, platformNetwork_t *platformNetwork)
|
|
|
+{
|
|
|
+ platformNetwork->socket = -1;
|
|
|
+ return RyanMqttSuccessError;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* @brief 连接mqtt服务器
|
|
|
*
|
|
|
@@ -20,69 +46,55 @@ RyanMqttError_e platformNetworkConnect(void *userData, platformNetwork_t *platfo
|
|
|
{
|
|
|
RyanMqttError_e result = RyanMqttSuccessError;
|
|
|
|
|
|
- // ?线程安全版本,有些设备没有实现,默认不启用。如果涉及多个客户端解析域名请使用线程安全版本
|
|
|
- char buf[512];
|
|
|
- int ret;
|
|
|
- struct hostent hostinfo, *phost;
|
|
|
+ struct hostent hostinfo = {0};
|
|
|
|
|
|
- if (0 != gethostbyname_r(host, &hostinfo, buf, sizeof(buf), &phost, &ret))
|
|
|
+ // 解析域名信息
|
|
|
{
|
|
|
- result = RyanSocketFailedError;
|
|
|
- goto exit;
|
|
|
+ char buf[512];
|
|
|
+ int h_errnop;
|
|
|
+ struct hostent *phost;
|
|
|
+
|
|
|
+ if (0 != gethostbyname_r(host, &hostinfo, buf, sizeof(buf), &phost, &h_errnop))
|
|
|
+ {
|
|
|
+ rlog_w("平台可能不支持 gethostbyname_r 函数, 再次尝试使用 gethostbyname 获取域名信息");
|
|
|
+
|
|
|
+ // 非线程安全版本,请根据实际情况选择使用
|
|
|
+ // NOLINTNEXTLINE(concurrency-mt-unsafe)
|
|
|
+ struct hostent *phostinfo = gethostbyname(host);
|
|
|
+ if (NULL == phostinfo)
|
|
|
+ {
|
|
|
+ result = RyanMqttNoRescourceError;
|
|
|
+ goto __exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ hostinfo = *phostinfo;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
platformNetwork->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
|
|
|
if (platformNetwork->socket < 0)
|
|
|
{
|
|
|
result = RyanSocketFailedError;
|
|
|
- goto exit;
|
|
|
+ goto __exit;
|
|
|
}
|
|
|
|
|
|
- struct sockaddr_in server_addr;
|
|
|
- memset(&server_addr, 0, sizeof(server_addr));
|
|
|
- server_addr.sin_family = AF_INET;
|
|
|
- server_addr.sin_port = htons(port); // 指定端口号,这里使用HTTP默认端口80
|
|
|
- server_addr.sin_addr = *((struct in_addr *)hostinfo.h_addr_list[0]);
|
|
|
+ struct sockaddr_in server_addr = {
|
|
|
+ .sin_family = AF_INET,
|
|
|
+ .sin_port = htons(port), // 指定端口号
|
|
|
+ .sin_addr = *((struct in_addr *)hostinfo.h_addr_list[0]),
|
|
|
+ };
|
|
|
|
|
|
// 绑定套接字到主机地址和端口号
|
|
|
if (connect(platformNetwork->socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0)
|
|
|
{
|
|
|
platformNetworkClose(userData, platformNetwork);
|
|
|
result = RyanMqttSocketConnectFailError;
|
|
|
- goto exit;
|
|
|
+ goto __exit;
|
|
|
}
|
|
|
|
|
|
- // 非线程安全版本,请根据实际情况选择使用
|
|
|
- // struct hostent *hostinfo;
|
|
|
- // hostinfo = gethostbyname(host);
|
|
|
- // if (NULL == hostinfo)
|
|
|
- // {
|
|
|
- // result = RyanSocketFailedError;
|
|
|
- // goto exit;
|
|
|
- // }
|
|
|
-
|
|
|
- // platformNetwork->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
|
|
|
- // if (platformNetwork->socket < 0)
|
|
|
- // {
|
|
|
- // result = RyanSocketFailedError;
|
|
|
- // goto exit;
|
|
|
- // }
|
|
|
-
|
|
|
- // struct sockaddr_in server_addr;
|
|
|
- // memset(&server_addr, 0, sizeof(server_addr));
|
|
|
- // server_addr.sin_family = AF_INET;
|
|
|
- // server_addr.sin_port = htons(port); // 指定端口号,这里使用HTTP默认端口80
|
|
|
- // server_addr.sin_addr = *((struct in_addr *)hostinfo->h_addr_list[0]);
|
|
|
-
|
|
|
- // // 绑定套接字到主机地址和端口号
|
|
|
- // if (connect(platformNetwork->socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0)
|
|
|
- // {
|
|
|
- // platformNetworkClose(userData, platformNetwork);
|
|
|
- // result = RyanMqttSocketConnectFailError;
|
|
|
- // goto exit;
|
|
|
- // }
|
|
|
-
|
|
|
-exit:
|
|
|
+__exit:
|
|
|
+ if (RyanMqttSuccessError != result)
|
|
|
+ rlog_e("socket连接失败: %d", result);
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
@@ -109,48 +121,41 @@ RyanMqttError_e platformNetworkRecvAsync(void *userData, platformNetwork_t *plat
|
|
|
platformTimer_t timer = {0};
|
|
|
|
|
|
if (-1 == platformNetwork->socket)
|
|
|
- return RyanSocketFailedError;
|
|
|
+ {
|
|
|
+ rlog_e("对端关闭socket连接");
|
|
|
+ return RyanMqttNoRescourceError;
|
|
|
+ }
|
|
|
|
|
|
platformTimerCutdown(&timer, timeout);
|
|
|
|
|
|
while ((offset < recvLen) && (0 != timeOut2))
|
|
|
{
|
|
|
-
|
|
|
tv.tv_sec = timeOut2 / 1000;
|
|
|
tv.tv_usec = timeOut2 % 1000 * 1000;
|
|
|
|
|
|
- if (tv.tv_sec <= 0 && tv.tv_usec <= 100)
|
|
|
- {
|
|
|
- tv.tv_sec = 0;
|
|
|
- tv.tv_usec = 100;
|
|
|
- }
|
|
|
-
|
|
|
setsockopt(platformNetwork->socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)); // 设置错做模式为非阻塞
|
|
|
|
|
|
recvResult = recv(platformNetwork->socket, recvBuf + offset, recvLen - offset, 0);
|
|
|
if (0 == recvResult)
|
|
|
{
|
|
|
- rlog_d("对端关闭socket连接");
|
|
|
- return RyanSocketFailedError;
|
|
|
+ rlog_e("对端关闭socket连接");
|
|
|
+ return RyanMqttNoRescourceError;
|
|
|
}
|
|
|
-
|
|
|
- if (recvResult < 0) // 小于零,表示错误,个别错误不代表socket错误
|
|
|
+ else if (recvResult < 0) // 小于零,表示错误,个别错误不代表socket错误
|
|
|
{
|
|
|
- int32_t rt_errno = errno;
|
|
|
- // 下列3种表示没问题,但需要退出接收
|
|
|
- if (rt_errno == EAGAIN || // 套接字已标记为非阻塞,而接收操作被阻塞或者接收超时
|
|
|
- rt_errno == EWOULDBLOCK || // 发送时套接字发送缓冲区已满,或接收时套接字接收缓冲区为空
|
|
|
- rt_errno == EINTR || // 操作被信号中断
|
|
|
- rt_errno == ETIME) // 计时器过期
|
|
|
+ int32_t rt_errno = errno; // 似乎5.0.0以上版本需要使用 rt_get_errno
|
|
|
+
|
|
|
+ // 下列表示没问题,但需要退出接收
|
|
|
+ if (EAGAIN == rt_errno || // 套接字已标记为非阻塞,而接收操作被阻塞或者接收超时
|
|
|
+ EWOULDBLOCK == rt_errno || // 发送时套接字发送缓冲区已满,或接收时套接字接收缓冲区为空
|
|
|
+ EINTR == rt_errno || // 操作被信号中断
|
|
|
+ ETIME == rt_errno) // 计时器过期
|
|
|
{
|
|
|
- rlog_d("recvResult2: %d, errno: %d", recvResult, rt_errno);
|
|
|
- rlog_d("recvLen2: %d, timeout: %d", recvLen, timeout);
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- rlog_w("recvResult: %d, errno: %d", recvResult, rt_errno);
|
|
|
- rlog_w("recvLen: %d, timeout: %d", recvLen, timeout);
|
|
|
-
|
|
|
+ // NOLINTNEXTLINE(concurrency-mt-unsafe)
|
|
|
+ rlog_e("recvResult: %d, errno: %d str: %s", recvResult, rt_errno, strerror(rt_errno));
|
|
|
return RyanSocketFailedError;
|
|
|
}
|
|
|
|
|
|
@@ -162,90 +167,6 @@ RyanMqttError_e platformNetworkRecvAsync(void *userData, platformNetwork_t *plat
|
|
|
return RyanMqttRecvPacketTimeOutError;
|
|
|
|
|
|
return RyanMqttSuccessError;
|
|
|
-
|
|
|
- // int32_t recvResult = 0;
|
|
|
- // int32_t offset = 0;
|
|
|
- // int32_t timeOut2 = timeout;
|
|
|
- // struct timeval tv = {0};
|
|
|
- // platformTimer_t timer = {0};
|
|
|
-
|
|
|
- // if (-1 == platformNetwork->socket)
|
|
|
- // return RyanSocketFailedError;
|
|
|
-
|
|
|
- // platformTimerCutdown(&timer, timeout);
|
|
|
-
|
|
|
- // while ((offset < recvLen) && (0 != timeOut2))
|
|
|
- // {
|
|
|
-
|
|
|
- // tv.tv_sec = timeOut2 / 1000;
|
|
|
- // tv.tv_usec = timeOut2 % 1000 * 1000;
|
|
|
-
|
|
|
- // if (tv.tv_sec <= 0 && tv.tv_usec <= 100)
|
|
|
- // {
|
|
|
- // tv.tv_sec = 0;
|
|
|
- // tv.tv_usec = 100;
|
|
|
- // }
|
|
|
-
|
|
|
- // fd_set readset;
|
|
|
- // fd_set exceptset;
|
|
|
- // int i, maxfdp1;
|
|
|
-
|
|
|
- // /* 清空可读事件描述符列表 */
|
|
|
- // FD_ZERO(&readset);
|
|
|
- // FD_ZERO(&exceptset);
|
|
|
-
|
|
|
- // FD_SET(platformNetwork->socket, &readset); // 监听可读事件
|
|
|
- // FD_SET(platformNetwork->socket, &exceptset); // 监听异常事件
|
|
|
-
|
|
|
- // /* 等待设定的网络描述符有事件发生 */
|
|
|
- // i = select(platformNetwork->socket + 1, &readset, NULL, &exceptset, &tv);
|
|
|
- // if (i < 0)
|
|
|
- // {
|
|
|
- // int32_t err = errno;
|
|
|
-
|
|
|
- // // 下列3种表示没问题,但需要退出接收
|
|
|
- // if (err == EAGAIN || // 套接字已标记为非阻塞,而接收操作被阻塞或者接收超时
|
|
|
- // err == EWOULDBLOCK || // 发送时套接字发送缓冲区已满,或接收时套接字接收缓冲区为空
|
|
|
- // err == EINTR) // 操作被信号中断
|
|
|
- // break;
|
|
|
-
|
|
|
- // return RyanSocketFailedError;
|
|
|
- // }
|
|
|
- // /* 查看 sock 描述符上有没有发生可读事件 */
|
|
|
- // else if (i > 0)
|
|
|
- // {
|
|
|
- // if (FD_ISSET(platformNetwork->socket, &readset))
|
|
|
- // {
|
|
|
- // recvResult = recv(platformNetwork->socket, recvBuf + offset, recvLen - offset, 0);
|
|
|
-
|
|
|
- // if (recvResult <= 0) // 小于零,表示错误,个别错误不代表socket错误
|
|
|
- // {
|
|
|
- // int32_t err = errno;
|
|
|
- // // 下列3种表示没问题,但需要退出接收
|
|
|
- // if (err == EAGAIN || // 套接字已标记为非阻塞,而接收操作被阻塞或者接收超时
|
|
|
- // err == EWOULDBLOCK || // 发送时套接字发送缓冲区已满,或接收时套接字接收缓冲区为空
|
|
|
- // err == EINTR) // 操作被信号中断
|
|
|
- // break;
|
|
|
-
|
|
|
- // return RyanSocketFailedError;
|
|
|
- // }
|
|
|
-
|
|
|
- // offset += recvResult;
|
|
|
- // }
|
|
|
-
|
|
|
- // if (FD_ISSET(platformNetwork->socket, &exceptset))
|
|
|
- // {
|
|
|
- // return RyanSocketFailedError;
|
|
|
- // }
|
|
|
- // }
|
|
|
-
|
|
|
- // timeOut2 = platformTimerRemain(&timer);
|
|
|
- // }
|
|
|
-
|
|
|
- // if (offset != recvLen)
|
|
|
- // return RyanMqttRecvPacketTimeOutError;
|
|
|
-
|
|
|
- // return RyanMqttSuccessError;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -271,45 +192,41 @@ RyanMqttError_e platformNetworkSendAsync(void *userData, platformNetwork_t *plat
|
|
|
platformTimer_t timer = {0};
|
|
|
|
|
|
if (-1 == platformNetwork->socket)
|
|
|
- return RyanSocketFailedError;
|
|
|
+ {
|
|
|
+ rlog_e("对端关闭socket连接");
|
|
|
+ return RyanMqttNoRescourceError;
|
|
|
+ }
|
|
|
|
|
|
platformTimerCutdown(&timer, timeout);
|
|
|
|
|
|
while ((offset < sendLen) && (0 != timeOut2))
|
|
|
{
|
|
|
-
|
|
|
tv.tv_sec = timeOut2 / 1000;
|
|
|
tv.tv_usec = timeOut2 % 1000 * 1000;
|
|
|
|
|
|
- if (tv.tv_sec <= 0 && tv.tv_usec <= 100)
|
|
|
- {
|
|
|
- tv.tv_sec = 0;
|
|
|
- tv.tv_usec = 100;
|
|
|
- }
|
|
|
-
|
|
|
setsockopt(platformNetwork->socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(struct timeval)); // 设置错做模式为非阻塞
|
|
|
|
|
|
sendResult = send(platformNetwork->socket, sendBuf + offset, sendLen - offset, 0);
|
|
|
if (0 == sendResult)
|
|
|
{
|
|
|
- rlog_d("对端关闭socket连接");
|
|
|
- return RyanSocketFailedError;
|
|
|
+ rlog_e("对端关闭socket连接");
|
|
|
+ return RyanMqttNoRescourceError;
|
|
|
}
|
|
|
-
|
|
|
- if (sendResult < 0) // 小于零,表示错误,个别错误不代表socket错误
|
|
|
+ else if (sendResult < 0) // 小于零,表示错误,个别错误不代表socket错误
|
|
|
{
|
|
|
- int32_t rt_errno = errno;
|
|
|
- rlog_d("sendResult: %d, errno: %d", sendResult, rt_errno);
|
|
|
- rlog_d("sendLen: %d, timeout: %d", sendLen, timeout);
|
|
|
- // 下列3种表示没问题,但需要退出发送
|
|
|
- if (rt_errno == EAGAIN || // 套接字已标记为非阻塞,而接收操作被阻塞或者接收超时
|
|
|
- rt_errno == EWOULDBLOCK || // 发送时套接字发送缓冲区已满,或接收时套接字接收缓冲区为空
|
|
|
- rt_errno == EINTR || // 操作被信号中断
|
|
|
- rt_errno == ETIME) // 计时器过期
|
|
|
+ int32_t rt_errno = errno; // 似乎5.0.0以上版本需要使用 rt_get_errno
|
|
|
+
|
|
|
+ // 下列表示没问题,但需要退出发送
|
|
|
+ if (EAGAIN == rt_errno || // 套接字已标记为非阻塞,而接收操作被阻塞或者接收超时
|
|
|
+ EWOULDBLOCK == rt_errno || // 发送时套接字发送缓冲区已满,或接收时套接字接收缓冲区为空
|
|
|
+ EINTR == rt_errno || // 操作被信号中断
|
|
|
+ ETIME == rt_errno) // 计时器过期
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
+ // NOLINTNEXTLINE(concurrency-mt-unsafe)
|
|
|
+ rlog_e("sendResult: %d, errno: %d str: %s", sendResult, rt_errno, strerror(rt_errno));
|
|
|
return RyanSocketFailedError;
|
|
|
}
|
|
|
|
|
|
@@ -321,58 +238,6 @@ RyanMqttError_e platformNetworkSendAsync(void *userData, platformNetwork_t *plat
|
|
|
return RyanMqttSendPacketTimeOutError;
|
|
|
|
|
|
return RyanMqttSuccessError;
|
|
|
-
|
|
|
- // int32_t sendResult = 0;
|
|
|
- // int32_t offset = 0;
|
|
|
- // int32_t timeOut2 = timeout;
|
|
|
- // struct timeval tv = {0};
|
|
|
- // platformTimer_t timer = {0};
|
|
|
-
|
|
|
- // if (-1 == platformNetwork->socket)
|
|
|
- // return RyanSocketFailedError;
|
|
|
-
|
|
|
- // platformTimerCutdown(&timer, timeout);
|
|
|
-
|
|
|
- // while ((offset < sendLen) && (0 != timeOut2))
|
|
|
- // {
|
|
|
-
|
|
|
- // tv.tv_sec = timeOut2 / 1000;
|
|
|
- // tv.tv_usec = timeOut2 % 1000 * 1000;
|
|
|
-
|
|
|
- // if (tv.tv_sec <= 0 && tv.tv_usec <= 100)
|
|
|
- // {
|
|
|
- // tv.tv_sec = 0;
|
|
|
- // tv.tv_usec = 100;
|
|
|
- // }
|
|
|
-
|
|
|
- // setsockopt(platformNetwork->socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(struct timeval)); // 设置错做模式为非阻塞
|
|
|
-
|
|
|
- // sendResult = send(platformNetwork->socket, sendBuf + offset, sendLen - offset, 0);
|
|
|
- // if (0 == sendResult)
|
|
|
- // {
|
|
|
- // rlog_d("对端关闭socket连接");
|
|
|
- // return RyanSocketFailedError;
|
|
|
- // }
|
|
|
- // else if (sendResult < 0) // 小于零,表示错误,个别错误不代表socket错误
|
|
|
- // {
|
|
|
- // int32_t err = errno;
|
|
|
- // // 下列3种表示没问题,但需要退出发送
|
|
|
- // if (err == EAGAIN || // 套接字已标记为非阻塞,而接收操作被阻塞或者接收超时
|
|
|
- // err == EWOULDBLOCK || // 发送时套接字发送缓冲区已满,或接收时套接字接收缓冲区为空
|
|
|
- // err == EINTR) // 操作被信号中断
|
|
|
- // break;
|
|
|
-
|
|
|
- // return RyanSocketFailedError;
|
|
|
- // }
|
|
|
-
|
|
|
- // offset += sendResult;
|
|
|
- // timeOut2 = platformTimerRemain(&timer);
|
|
|
- // }
|
|
|
-
|
|
|
- // if (offset != sendLen)
|
|
|
- // return RyanMqttSendPacketTimeOutError;
|
|
|
-
|
|
|
- // return RyanMqttSuccessError;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -388,6 +253,7 @@ RyanMqttError_e platformNetworkClose(void *userData, platformNetwork_t *platform
|
|
|
if (platformNetwork->socket >= 0)
|
|
|
{
|
|
|
closesocket(platformNetwork->socket);
|
|
|
+ rlog_w("platformNetworkClose socket close %d", platformNetwork->socket);
|
|
|
platformNetwork->socket = -1;
|
|
|
}
|
|
|
|