当前位置: 首页 > news >正文

在LwIP中,`tcp_recved()`、`tcp_sndbuf()` 和 `tcp_write()`三个函数详细用法及示例

在LwIP中,tcp_recved()tcp_sndbuf()tcp_write() 是TCP协议栈的核心函数,用于管理接收和发送数据流。以下是它们的详细用法及示例:


1. tcp_recved()

功能
  • 通知协议栈已处理接收数据:当应用层从接收缓冲区读取数据后,需调用此函数更新TCP接收窗口(Window Size),允许对端继续发送数据。
  • 流量控制:避免接收缓冲区溢出,确保TCP滑动窗口机制正常工作。
函数原型
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;
}

2. tcp_sndbuf()

功能
  • 获取发送缓冲区剩余空间:返回当前TCP连接发送缓冲区中可用的字节数。
  • 避免发送阻塞:在调用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)
    }
}

3. tcp_write()

功能
  • 将数据写入发送缓冲区:将应用层数据提交到TCP发送缓冲区,等待协议栈发送。
  • 数据分片:自动根据MSS(最大报文段长度)分片,或通过标志控制立即发送。
函数原型
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); // 立即发送数据
    }
}

三函数协作流程

  1. 接收数据
    • tcp_recv()回调中处理数据 → 调用tcp_recved()更新窗口。
  2. 发送数据
    • 调用tcp_sndbuf()检查空间 → 调用tcp_write()写入数据 → 调用tcp_output()触发发送。

常见问题与解决

1. 数据发送不出去
  • 原因:未调用tcp_output(),数据滞留在缓冲区。
  • 解决:写入后显式调用tcp_output()或使用TCP_WRITE_FLAG_MORE标志。
2. 接收端停滞
  • 原因:未调用tcp_recved(),接收窗口未更新。
  • 解决:处理完数据后立即调用tcp_recved()
3. 发送返回ERR_MEM
  • 原因:发送缓冲区满。
  • 解决:分片发送或注册tcp_sent()回调,在缓冲区空闲时重试。

完整示例(TCP Echo服务器)

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通信的稳定性和效率。

相关文章:

  • 【QT】Q_GLOBAL_STATIC的使用
  • 免费提供多样风格手机壁纸及自动更换功能的软件
  • 高速网络包处理,基础网络协议上内核态直接处理数据包,XDP技术的原理
  • C#实现自己的Json解析器(LALR(1)+miniDFA)
  • 正则表达式详解(regular expression)
  • 数据库连接不上,端口号为0?
  • CLR 线程池
  • 构建第二个Django的应用程序
  • Androidstudio出现警告warning:意外的元素
  • 《Linux系统编程篇》Linux Socket 网络编程01 API介绍(Linux 进程间通信(IPC))——基础篇
  • 学习知识的心理和方法杂记-04
  • HTML和CSS基础
  • Windows部署deepseek R1训练数据后通过AnythingLLM当服务器创建问答页面
  • mysql之DATE_FORMAT迁移到gbase8s
  • Linux设置串口永久权限
  • Flutter运行错误:UG! exception in phase ‘semantic analysis‘
  • 2024年河南省职业院校 技能大赛高职组 “大数据分析与应用” 赛项任务书(四)
  • Jetson Nano配置指南(四):YOLOv8/v11使用TensorRT加速
  • A l密码学(Deepseek)
  • 超硬核区块链算法仿真:联盟链PBFT多线程仿真实现 :c语言完全详解版
  • 上海天文馆走进徐家汇书院,XR沉浸式天文科普体验再推力作
  • 女子七年后才知银行卡被盗刷18万元,警方抓获其前男友
  • 特朗普再提“接管”加沙,要将其变为“自由区”
  • 埃尔多安:愿在土耳其促成俄乌领导人会晤
  • 苏轼“胡为适南海”?
  • 思想史家陈谷嘉逝世,曾为岳麓书院当代复兴奠定重要基础