forked from gary/ems
2
0
Fork 0
sun_ems/ems_c/driver/drv_tcp_client.c

248 lines
7.5 KiB
C
Raw Normal View History

2025-05-13 17:49:49 +08:00
/*****************************************************************************
* @copyright 2024-202, . POWER SUPPLY CO., LTD.
* @file drv_tcp.c
* @brief tcp驱动文件
* @author Gary
* @date 2024/08/30
* @remark
*****************************************************************************/
#include "drv_tcp_client.h"
/*****************************************************************************
* @brief IP地址类型
* @param[in] ip地址
* @return 1: IPv4, 2: IPv6, 0:
*****************************************************************************/
static int is_ip(const char *ip)
{
struct sockaddr_in sa;
if (inet_pton(AF_INET, ip, &(sa.sin_addr)) != 0)
{
return 1;
}
struct sockaddr_in6 sa6;
if (inet_pton(AF_INET6, ip, &(sa6.sin6_addr)) != 0)
{
return 2;
}
return 0;
}
/*****************************************************************************
* @brief
* @param[in] str
* @param[in] data
* @param[in] len
* @return void
*****************************************************************************/
static void tcpPrintLog(const char *str, uint8_t *data, uint16_t len)
{
char sdata[512 * 2] = {0};
int pos = 0;
if ((uint8_t)getRtdbPointValue(rtdbType, kDev_Type_EMS, 0, kEms_TcpLog_Enable) == 1)
{
if (len > 0)
{
for (int i = 0; i < len; i++)
{
pos += snprintf(sdata + pos, sizeof(sdata) - pos, "%02x ", data[i]);
// 检查snprintf返回值确保写入成功并处理潜在错误
if (pos < 0 || pos >= sizeof(sdata))
{
KITPTF(LOG_DRIVER_EN, ERROR_EN, "tcpPrintLog: snprintf failed!");
break; // 停止继续处理
}
}
// 使用snprintf避免缓冲区溢出
pos += snprintf(sdata + pos, sizeof(sdata) - pos, "\n");
// 检查snprintf返回值确保写入成功并处理潜在错误
if (pos < 0 || pos >= sizeof(sdata))
{
KITPTF(LOG_DRIVER_EN, ERROR_EN, "tcpPrintLog: snprintf failed!");
}
}
KITPTF(LOG_DRIVER_EN, INFO_EN, "%s:%s", str, sdata);
KITLOG(LOG_DRIVER_EN, INFO_EN, "%s:%s", str, sdata);
}
}
/*****************************************************************************
* @brief tcp驱动
* @param[in] p_tcp: tcp驱动结构体指针
* @return 0- 1-
*****************************************************************************/
int drvTcpOpen(tcp_client_lib_t *p_tcp)
{
// 判断IP地址类型1: IPv4, 2: IPv6, 0: 无效地址
int ip_type = is_ip(p_tcp->ip);
if (ip_type == 0)
{
KITLOG(LOG_DRIVER_EN, ERROR_EN, "无效 ip: %s", p_tcp->ip);
return 1;
}
p_tcp->socket_fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in remote_in;
remote_in.sin_family = AF_INET;
remote_in.sin_port = htons(p_tcp->port);
if (inet_pton(AF_INET, p_tcp->ip, &remote_in.sin_addr) <= 0)
{
KITLOG(LOG_DRIVER_EN, ERROR_EN, "Invalid address or address not supported");
return 1;
}
if (p_tcp->socket_fd == -1)
{
KITLOG(LOG_DRIVER_EN, ERROR_EN, "socket 错误: %s(%d)\n", strerror(errno), errno);
return 1;
}
int ret = connect(p_tcp->socket_fd, (struct sockaddr *)&remote_in, sizeof(struct sockaddr_in));
if (ret == -1)
{
KITLOG(LOG_DRIVER_EN, ERROR_EN, "连接错误: %s(%d)\n", strerror(errno), errno);
KITPTF(LOG_DRIVER_EN, ERROR_EN, "连接错误: %s(%d)\n", strerror(errno), errno);
close(p_tcp->socket_fd);
return 1;
}
return 0; // 返回成功
}
/*****************************************************************************
* @brief tcp驱动
* @param[in] p_tcp: tcp驱动结构体指针
* @return 0- 1-
*****************************************************************************/
int drvTcpClose(tcp_client_lib_t *p_tcp)
{
if (p_tcp->socket_fd > 0)
{
close(p_tcp->socket_fd);
p_tcp->socket_fd = 0;
p_tcp->status = CONN_OFFLINE;
}
else
{
perror("Close fail!");
return 1;
}
return 0;
}
/*****************************************************************************
* @brief tcp驱动发送
* @param[in] p_tcp: tcp驱动结构体指针
* @return 0- 1-
*****************************************************************************/
int drvTcpSend(tcp_client_lib_t *p_tcp)
{
ssize_t ret = 0;
fd_set writefds;
struct timeval timeout;
timeout.tv_sec = 3; // 3秒超时
timeout.tv_usec = 0;
FD_ZERO(&writefds);
FD_SET(p_tcp->socket_fd, &writefds);
int retn = select(p_tcp->socket_fd + 1, NULL, &writefds, NULL, &timeout);
if (retn > 0 && FD_ISSET(p_tcp->socket_fd, &writefds))
{
goto sendpos;
}
else if (retn == 0)
{
KITLOG(LOG_DRIVER_EN, ERROR_EN, "Socket write timeout");
return 1;
}
else
{
// 发生错误
KITLOG(LOG_DRIVER_EN, ERROR_EN, "IP(%s) 发送错误! ret: %ld, errno: %s(%d)\n",
p_tcp->ip, ret, strerror(errno), errno);
// close(p_tcp->socket_fd); // 关闭 socket 协议层面去关闭,驱动层面不做处理,否则灵敏度过高
return 128;
}
sendpos:
while (ret < p_tcp->send_len)
{
ssize_t rc = send(p_tcp->socket_fd, p_tcp->send_buf + ret, p_tcp->send_len - ret, MSG_NOSIGNAL);
if (rc > 0)
{
ret += rc;
}
else
{
// 发生错误
if (rc < 0)
{
KITLOG(LOG_DRIVER_EN, ERROR_EN, "IP(%s) 发送错误! ret: %ld, errno: %s(%d)\n",
p_tcp->ip, ret, strerror(errno), errno);
KITPTF(LOG_DRIVER_EN, ERROR_EN, "IP(%s) 发送错误! ret: %ld, errno: %s(%d)\n",
p_tcp->ip, ret, strerror(errno), errno);
}
return 1;
}
}
tcpPrintLog("发送数据:", p_tcp->send_buf, p_tcp->send_len);
return 0;
}
/*****************************************************************************
* @brief tcp驱动接收
* @param[in] p_tcp: tcp驱动结构体指针
* @return 0- 1-
*****************************************************************************/
int drvTcpRecv(tcp_client_lib_t *p_tcp)
{
// 超时时间检测
if (0 != p_tcp->timeout)
{
fd_set set;
FD_ZERO(&set);
FD_SET(p_tcp->socket_fd, &set);
// 最大阻塞30s
if (p_tcp->timeout / 1000 > 30)
{
p_tcp->timeout = 30 * 1000;
}
struct timeval time_out = {p_tcp->timeout / 1000, (p_tcp->timeout % 1000) * 1000};
// 检测超时时间
int ret = select(p_tcp->socket_fd + 1, &set, NULL, NULL, &time_out);
if (0 == ret)
{
return -128;
}
else if (ret < 0)
{
return -1;
}
}
p_tcp->recv_len = recv(p_tcp->socket_fd, p_tcp->recv_buf, MAX_TCP_REV_LEN, 0);
if (p_tcp->recv_len < 0)
{
p_tcp->recv_len = 0;
return -1;
}
else if (0 == p_tcp->recv_len)
{
return -128;
}
else
{
tcpPrintLog("接收数据:", p_tcp->recv_buf, p_tcp->recv_len);
}
return 0;
}