在LwIP中,tcp_recved()
、tcp_sndbuf()
和 tcp_write()
是TCP协议栈的核心函数,用于管理接收和发送数据流。以下是它们的详细用法及示例:
tcp_recved()
void tcp_recved(struct tcp_pcb *pcb, u16_t len);
pcb
:指向当前TCP连接的tcp_pcb
结构体。len
:应用层已处理的数据长度(字节)。tcp_recv()
注册的回调)中处理完数据后调用。err_t my_recv_callback(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) {
if (p != NULL) {
// 处理接收到的数据(例如拷贝到应用缓冲区)
process_data(p->payload, p->len);
// 通知协议栈已处理数据长度
tcp_recved(pcb, p->tot_len);
// 释放pbuf
pbuf_free(p);
} else if (err == ERR_OK) {
// 对端关闭连接
tcp_close(pcb);
}
return ERR_OK;
}
tcp_sndbuf()
tcp_write()
前检查可用空间,防止因缓冲区不足导致写入失败。u16_t tcp_sndbuf(struct tcp_pcb *pcb);
pcb
:指向当前TCP连接的tcp_pcb
结构体。void send_data(struct tcp_pcb *pcb, const char *data, u16_t len) {
// 检查发送缓冲区剩余空间
u16_t available = tcp_sndbuf(pcb);
if (available < len) {
// 空间不足,等待或分片发送
len = available;
}
// 写入数据到发送缓冲区
err_t err = tcp_write(pcb, data, len, TCP_WRITE_FLAG_COPY);
if (err == ERR_OK) {
// 触发数据发送
tcp_output(pcb);
} else {
// 处理错误(如ERR_MEM)
}
}
tcp_write()
err_t tcp_write(struct tcp_pcb *pcb, const void *data, u16_t len, u8_t flags);
pcb
:指向当前TCP连接的tcp_pcb
结构体。data
:待发送数据的指针。len
:数据长度(字节)。flags
:控制标志,常用值:
TCP_WRITE_FLAG_COPY
:复制数据到内部缓冲区(默认推荐)。TCP_WRITE_FLAG_MORE
:提示后续还有数据,延迟发送(结合tcp_output()
触发)。ERR_OK
:写入成功。ERR_MEM
:缓冲区不足。ERR_CONN
:连接已关闭。// 发送HTTP响应
const char *response = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nHello";
u16_t resp_len = strlen(response);
// 检查发送缓冲区空间
if (tcp_sndbuf(pcb) >= resp_len) {
// 写入数据并立即发送
err_t err = tcp_write(pcb, response, resp_len, TCP_WRITE_FLAG_COPY);
if (err == ERR_OK) {
tcp_output(pcb); // 立即发送数据
}
}
tcp_recv()
回调中处理数据 → 调用tcp_recved()
更新窗口。tcp_sndbuf()
检查空间 → 调用tcp_write()
写入数据 → 调用tcp_output()
触发发送。tcp_output()
,数据滞留在缓冲区。tcp_output()
或使用TCP_WRITE_FLAG_MORE
标志。tcp_recved()
,接收窗口未更新。tcp_recved()
。ERR_MEM
tcp_sent()
回调,在缓冲区空闲时重试。err_t echo_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) {
if (p != NULL) {
// 回传接收到的数据
tcp_write(pcb, p->payload, p->len, TCP_WRITE_FLAG_COPY);
tcp_output(pcb);
// 通知协议栈已处理数据
tcp_recved(pcb, p->len);
pbuf_free(p);
} else if (err == ERR_OK) {
tcp_close(pcb);
}
return ERR_OK;
}
// 初始化TCP服务器
void tcp_server_init() {
struct tcp_pcb *pcb = tcp_new();
tcp_bind(pcb, IP_ADDR_ANY, 8080);
tcp_listen(pcb);
tcp_accept(pcb, [](void *arg, struct tcp_pcb *newpcb, err_t err) {
tcp_recv(newpcb, echo_recv);
return ERR_OK;
});
}
通过合理使用这三个函数,可以确保LwIP TCP通信的稳定性和效率。