一、理论部分
使用接收缓冲区来缓存对方发来的数据

二、代码实现部分
在tcp控制块添加接收缓冲区字段
cpp
struct _xtcp_t
{
xtcp_state_t state;
uint16_t local_port, remote_port;
xipaddr_t remote_ip;
uint32_t unack_seq, next_seq;
uint32_t ack;
uint16_t remote_mss;
uint16_t remote_win;
xtcp_handler_t handler;
xtcp_buf_t tx_buf, rx_buf;
};
在tcp_alloc函数中初始化rx_buf
cpp
static xtcp_t* tcp_alloc(void)
{
xtcp_t* tcp, * end;
for (tcp = tcp_socket, end = tcp_socket + XTCP_CFG_MAX_TCP; tcp < end; tcp++)
{
if (tcp->state == XTCP_STATE_FREE)
{
tcp->state = XTCP_STATE_CLOSED;
tcp->local_port = 0;
tcp->remote_port = 0;
tcp->remote_ip.addr = 0;
tcp->handler = (xtcp_handler_t)0;
tcp->remote_win = XTCP_MSS_DEFAULT;
tcp->remote_mss = XTCP_MSS_DEFAULT;
tcp->unack_seq = tcp->next_seq = tcp_get_init_seq();
tcp->ack = 0;
tcp_buf_init(&tcp->tx_buf);
tcp_buf_init(&tcp->rx_buf);
return tcp;
}
}
return (xtcp_t*)0;
}
在http_handler当中测试TCP对于数据的收发功能
cpp
static uint8_t rx_buffer[1024];
static xnet_err_t http_handler(xtcp_t* tcp, xtcp_conn_state_t state)
{
static char* num = "0123456789ABCDEF";
if (state == XTCP_CONN_CONNECTED)
{
printf("http connected.\n");
}
else if (state == XTCP_CONN_CLOSED)
{
printf("http closed.\n");
}
else if (state == XTCP_CONN_DATA_RECV)
{
uint8_t* data = rx_buffer;
uint16_t read_size = xtcp_read(tcp, rx_buffer, sizeof(rx_buffer));
while (read_size)
{
uint16_t curr_size = xtcp_write(tcp, data, read_size);
data += curr_size;
read_size -= curr_size;
}
}
return XNET_ERR_OK;
}
xtcp_read函数实现:
cpp
uint16_t xtcp_read(xtcp_t* tcp, uint8_t* data, uint16_t size)
{
return tcp_buf_read(&tcp->rx_buf, data, size);
}
tcp_buf_read函数实现:
cpp
static uint16_t tcp_buf_read(xtcp_buf_t* tcp_buf, uint8_t* to, uint16_t size)
{
int i;
size = min(size, tcp_buf->data_count);
for (i = 0; i < size; i++)
{
*to++ = tcp_buf->data[tcp_buf->tail++];
if (tcp_buf->tail >= XTCP_CFG_RTX_BUF_SIZE)
{
tcp_buf->tail = 0;
}
}
tcp_buf->data_count -= size;
return size;
}
在xtcp_in当中添加TCP数据接收部分的处理
1)首先通过tcp_recv函数将packet->data当中的数据读取到接收缓冲区rx_buf
2)收到数据,回复ack,并处理接收的数据
cpp
else if (read_size)
{
tcp_send(tcp, XTCP_FLAG_ACK);
tcp->handler(tcp, XTCP_CONN_DATA_RECV);
}
完整处理TCP数据接收的代码:
cpp
case XTCP_STATE_ESTABLISHED:
{
if (tcp_hdr->hdr_flags.flags & (XTCP_FLAG_ACK | XTCP_FLAG_FIN))
{
if (tcp_hdr->hdr_flags.flags & XTCP_FLAG_ACK)
{
if ((tcp_hdr->ack > tcp->unack_seq) && (tcp_hdr->ack <= tcp->next_seq))
{
uint16_t curr_ack_size = tcp_hdr->ack - tcp->unack_seq;
tcp_buf_add_acked_count(&tcp->tx_buf, curr_ack_size);
tcp->unack_seq += curr_ack_size;
}
}
read_size = tcp_recv(tcp, (uint8_t*)tcp_hdr->hdr_flags.flags, packet->data, packet->size);
if (tcp_hdr->hdr_flags.flags & XTCP_FLAG_FIN)
{
tcp->state = XTCP_STATE_LAST_ACK;
tcp->ack++;
tcp_send(tcp, XTCP_FLAG_FIN | XTCP_FLAG_ACK);
}
else if (read_size)
{
tcp_send(tcp, XTCP_FLAG_ACK);
tcp->handler(tcp, XTCP_CONN_DATA_RECV);
}
else if (tcp_buf_wait_send_count(&tcp->tx_buf))
{
tcp_send(tcp, XTCP_FLAG_ACK);
}
}
break;
}
其中tcp_recv函数实现:
cpp
static uint16_t tcp_recv(xtcp_t* tcp, uint8_t flags, uint8_t* from, uint16_t size)
{
uint16_t read_size = tcp_buf_write(&tcp->rx_buf, from, size);
tcp->ack += read_size;
return read_size;
}
最后在tcp_send函数当中,把发送窗口的大小动态调整一下:
cpp
tcp_hdr->window = swap_order16(tcp_buf_free_count(&tcp->rx_buf));
三、测试部分


ok,今天的你就到此为止吧,明天还要接着🐺啊!