#include "plat_comm/lwip_module/lwip_module.h" #include "lwip/sockets.h" /* LwIP socket API(socket/connect/send/recv/close) */ #include "lwip/netdb.h" /* 域名解析 lwip_gethostbyname */ #include #include /** * ************************************************************************ * @brief 将主机名或 IP 字符串解析为 in_addr * @param[in] host - 服务器地址,可为 "192.168.1.1" 或 "www.xxx.com" * @param[out] out_addr - 解析得到的 IPv4 地址 * @return 0 成功,-1 失败(非 IP 且 DNS 解析失败) * ************************************************************************ */ int lwip_resolve_host(const char *host, struct in_addr *out_addr) { if (host == NULL || out_addr == NULL) return -1; /* 先按 IP 字符串解析(如 "134.17.16.109") */ unsigned long addr = inet_addr(host); if (addr != INADDR_NONE) { out_addr->s_addr = addr; return 0; } /* 非 IP 则按域名解析(依赖 LwIP DNS,仅 LWIP_DNS=1 时 netdb.h 才声明 lwip_gethostbyname) */ #if LWIP_DNS { struct hostent *he = lwip_gethostbyname(host); if (he != NULL && he->h_addr_list[0] != NULL) { memcpy(&out_addr->s_addr, he->h_addr_list[0], (size_t)he->h_length); return 0; } } #endif return -1; } /** * ************************************************************************ * @brief 设置 socket 为非阻塞模式 * @param[in] sock - socket 描述符 * @return 0 成功,-1 失败 * ************************************************************************ */ int lwip_set_nonblock(int sock) { int flags = lwip_fcntl(sock, F_GETFL, 0); if (flags >= 0) { if (lwip_fcntl(sock, F_SETFL, flags | O_NONBLOCK) >= 0) return 0; } return -1; } /** * ************************************************************************ * @brief 创建 TCP socket 并连接到指定地址 * @param[in] host - 服务器地址(IP 或域名) * @param[in] port - 服务器端口 * @return >=0 socket 描述符,<0 失败 * ************************************************************************ */ int lwip_tcp_connect(const char *host, uint16_t port) { struct sockaddr_in server_addr; struct in_addr ip_addr; int sock; if (host == NULL || host[0] == '\0' || port == 0) return -1; /* 创建 TCP 流式 socket */ sock = lwip_socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) return -1; /* 解析服务器 host(IP 或域名)为 in_addr */ if (lwip_resolve_host(host, &ip_addr) != 0) { lwip_close(sock); return -1; } /* 填充服务器地址并发起连接 */ memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = ip_addr.s_addr; server_addr.sin_port = htons(port); if (lwip_connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0) { lwip_close(sock); return -1; } /* 设为非阻塞,避免 recv 阻塞任务 */ if (lwip_set_nonblock(sock) != 0) { lwip_close(sock); return -1; } return sock; } /** * ************************************************************************ * @brief 关闭 socket * @param[in] sock - socket 描述符 * ************************************************************************ */ void lwip_tcp_close(int sock) { if (sock >= 0) lwip_close(sock); } /** * ************************************************************************ * @brief 发送数据 * @param[in] sock - socket 描述符 * @param[in] buf - 发送缓冲区 * @param[in] len - 发送长度 * @return >0 实际发送字节数,<=0 失败或对端关闭 * ************************************************************************ */ int lwip_tcp_send(int sock, const void *buf, size_t len) { if (sock < 0 || buf == NULL || len == 0) return -1; return lwip_send(sock, buf, len, 0); } /** * ************************************************************************ * @brief 接收数据(非阻塞) * @param[in] sock - socket 描述符 * @param[out] buf - 接收缓冲区 * @param[in] len - 缓冲区长度 * @return >0 实际接收字节数,0 对端关闭,<0 错误(errno 需检查) * ************************************************************************ */ int lwip_tcp_recv(int sock, void *buf, size_t len) { if (sock < 0 || buf == NULL || len == 0) return -1; return lwip_recv(sock, buf, len, 0); }