ZYNQ Lwip-TCP数据发送 tcp_write()、tcp_output() 、tcp_sent()

tcp_write()tcp_output()tcp_sent() 是在TCP通信过程中用于数据发送、控制和确认的关键函数,通常在一起配合使用。让我们通过详细讲解每个函数,并解释它们之间的关联。

1. tcp_write() —— 写数据到发送缓冲区

作用
tcp_write() 用于将用户数据写入到 TCP 的发送缓冲区中,并等待后续通过 TCP/IP 协议栈发送出去。该函数不会直接发送数据,而是将数据放入缓冲区,等待时机发送。

函数原型

err_t tcp_write(struct tcp_pcb *pcb,
                const void *data,
                u16_t len,
                u8_t apiflags);

参数

  • pcb:指向 TCP 控制块的指针,表示要发送数据的连接。
  • data:要发送的数据。
  • len:要发送的数据的长度(字节数)。
  • apiflags:API标志,常用值有:
    • TCP_WRITE_FLAG_COPY:表示复制数据到TCP的内部缓冲区。
    • TCP_WRITE_FLAG_MORE:表示还有后续数据,这个标志表明可以延迟发送(适合发送大量分段数据时使用)。

返回值
返回 ERR_OK 表示数据成功写入缓冲区,其他返回值(如 ERR_MEM)表示写入失败,通常是缓冲区空间不足。

2. tcp_output() —— 触发发送

作用
tcp_output() 用于强制将已经写入发送缓冲区的数据发送出去。它控制着实际的数据传输,tcp_write() 只是将数据放入缓冲区,而 tcp_output() 则是触发协议栈通过底层网络接口发送这些数据。

函数原型

err_t tcp_output(struct tcp_pcb *pcb);

参数

  • pcb:TCP 控制块的指针。

返回值
ERR_OK 表示成功调用发送操作,其他错误码可能指示网络资源不足或连接问题。

说明
tcp_output() 并不总是必须手动调用。在某些情况下(例如,协议栈定时器或事件触发),TCP 栈可能会自动发送缓冲区中的数据。但如果你希望数据立即发送出去,手动调用 tcp_output() 是必要的。

3. tcp_sent() —— 数据发送后的确认回调

作用
tcp_sent() 用于设置一个回调函数,当 TCP 数据成功发送并得到接收方的确认(即收到ACK包)后,TCP 协议栈会调用这个回调函数。这在流量控制和发送确认中非常重要,特别是当你需要确保数据已经安全传输时。

函数原型

void tcp_sent(struct tcp_pcb *pcb,
              tcp_sent_fn sent);

参数

  • pcb:TCP 控制块的指针。
  • sent:指向回调函数的指针,原型为:
    err_t sent(void *arg, struct tcp_pcb *pcb, u16_t len);
    
    其中 len 表示已经成功发送并确认的数据字节数。

4. 三个函数的工作流程

在实际使用中,tcp_write()tcp_output()tcp_sent() 往往配合使用,以确保数据的顺利发送和接收确认。以下是它们之间的典型工作流程:

客户端数据发送的流程:
  1. tcp_write():首先调用 tcp_write(),将需要发送的数据写入 TCP 的发送缓冲区。这只是数据写入缓冲区,并不会立即发送。

    err_t err = tcp_write(pcb, data, strlen(data), TCP_WRITE_FLAG_COPY);
    if (err != ERR_OK) {
        printf("Error writing TCP data: %d\n", err);
    }
    
  2. tcp_output():数据写入缓冲区后,调用 tcp_output() 触发数据传输,迫使协议栈将缓冲区中的数据发送出去。如果不调用 tcp_output(),发送操作可能会被协议栈延迟,直到某个事件(如接收到 ACK 包)发生。

    tcp_output(pcb);  // 强制发送
    
  3. tcp_sent():设置一个回调函数来监听数据传输的确认。当接收端成功收到数据并发送 ACK 包时,TCP 协议栈会调用 tcp_sent() 注册的回调函数,并传递成功发送的字节数。

    tcp_sent(pcb, my_sent_callback);
    
    // 回调函数
    err_t my_sent_callback(void *arg, struct tcp_pcb *pcb, u16_t len) {
        printf("Successfully sent %d bytes\n", len);
        return ERR_OK;
    }
    

完整发送流程总结:
  • tcp_write():将数据放入 TCP 缓冲区。
  • tcp_output():将缓冲区数据立即发送出去。
  • tcp_sent():设置回调函数,监听数据发送成功后的确认。

实际代码示例:

struct tcp_pcb *pcb;
const char *data = "Hello, World!";

// 写入数据到发送缓冲区
err_t err = tcp_write(pcb, data, strlen(data), TCP_WRITE_FLAG_COPY);
if (err != ERR_OK) {
    printf("Failed to write TCP data: %d\n", err);
}

// 强制发送缓冲区中的数据
tcp_output(pcb);

// 设置一个回调函数,当数据发送成功后得到确认
tcp_sent(pcb, my_sent_callback);

// 回调函数:发送成功时被调用
err_t my_sent_callback(void *arg, struct tcp_pcb *pcb, u16_t len) {
    printf("Successfully sent %d bytes\n", len);
    return ERR_OK;
}

总结:

  • tcp_write() 用于将数据写入发送缓冲区。
  • tcp_output() 用于强制发送缓冲区中的数据。
  • tcp_sent() 用于设置回调函数,以监听数据发送后的确认。

通过这三个函数,用户可以控制数据的发送、确保及时传输,并在接收确认后执行后续操作。

你可能感兴趣的:(LWIP,tcp/ip,网络,网络协议)