根据您的描述,问题核心在于ESP8266 AT组件的UDP服务器实现中,本地端口(local_port)未正确绑定。以下是具体原因分析和解决方案:
参数传递错误:
esp8266_socket_connect() 函数被调用时,传入的 port 参数是 远程端口(remote_port),而非绑定的本地端口(local_port)。AT+CIPSTART 指令需要 明确指定本地端口(用于监听),但当前实现未传递绑定的本地端口值。UDP服务器逻辑缺陷:
connect)使用了远程端口而非绑定的本地端口。bind() 操作保存了本地端口,但在后续 AT+CIPSTART 调用中未使用该值。AT指令格式不符:
AT+CIPSTART=,"UDP","",, 其中 local_port 是监听端口,但当前实现未正确填充该字段。
需修改 esp8266_socket_connect() 函数,确保绑定本地端口被传递到 AT+CIPSTART 指令。以下是具体步骤:
在 at_socket 结构体中添加字段存储绑定的本地端口:
struct at_socket {
int socket;
int type;
int state;
int recv_timeout;
int local_port; // 新增本地端口字段
};bind() 操作中记录端口在绑定函数中保存本地端口到结构体:
static int esp8266_socket_bind(struct at_socket *socket, const struct sockaddr *name, socklen_t namelen)
{
struct sockaddr_in *addr = (struct sockaddr_in *)name;
socket->local_port = ntohs(addr->sin_port); // 保存端口
return 0;
}esp8266_socket_connect() 函数在连接逻辑中使用绑定的本地端口:
static int esp8266_socket_connect(struct at_socket *socket, char *ip, int32_t port, enum at_socket_type type, rt_bool_t is_client)
{
char recv_ip[16] = {0};
int remote_port = port;
// UDP服务器逻辑:使用绑定的本地端口
if (type == AT_SOCKET_TYPE_UDP && !is_client)
{
// 格式: AT+CIPSTART=,"UDP","",,
at_send_cmd("AT+CIPSTART=%d,"UDP","%s",%d,%d",
socket->socket,
ip ? ip : "0",
remote_port,
socket->local_port); // 关键:传入绑定的本地端口
}
// ... 其他类型处理
} 确保在创建UDP服务器时调用 bind() 并设置 is_client = RT_FALSE:
// 创建UDP Socket
int sock = socket(AF_INET, SOCK_DGRAM, 0);
// 绑定本地端口
struct sockaddr_in local_addr;
memset(&local_addr, 0, sizeof(local_addr));
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(LOCAL_PORT); // 服务器监听端口
bind(sock, (struct sockaddr*)&local_addr, sizeof(local_addr));
// 连接配置(此时is_client设为RT_FALSE)
struct sockaddr_in remote_addr;
memset(&remote_addr, 0, sizeof(remote_addr));
remote_addr.sin_family = AF_INET;
remote_addr.sin_addr.s_addr = inet_addr("0"); // 任意远程IP
remote_addr.sin_port = htons(0); // 任意远程端口
connect(sock, (struct sockaddr*)&remote_addr, sizeof(remote_addr)); // 触发AT+CIPSTART| 步骤 | 修改内容 | 目的 |
|---|---|---|
| 1 | 在 struct at_socket 添加 local_port | 存储绑定的本地端口 |
| 2 | 在 bind() 中保存端口到结构体 | 记录监听端口值 |
| 3 | 修改 AT+CIPSTART 填入 local_port | 确保AT指令使用正确端口 |
| 4 | 连接时设置 is_client = RT_FALSE | 标识服务器模式 |
注意:ESP8266作为UDP服务器时,
AT+CIPSTART必须明确指定local_port,且需在bind()后调用connect()触发连接建立。远程IP/端口可设为0表示接收任意源地址数据包。
经此修改后,ESP8266将正确监听指定本地端口,实现UDP服务器功能。
举报
更多回帖