作者:我爱投资理财 | 来源:互联网 | 2023-09-02 05:42
2015年12月9日BY:TATERLITCP比UDP就复杂多了,UDP就像串口一样发发随便奶奶,但是TCP不是,有监听啊,查询啊什么,可以看看电脑的TCP连接,多得呢.所以,
2015年12月9日 BY : TATERLI
TCP比UDP就复杂多了,UDP就像串口一样发发随便奶奶,但是TCP不是,有监听啊,查询啊什么,可以看看电脑的TCP连接,多得呢.
所以,在官方的例子你们,TCP Client就是6个函数:
static err_t tcp_echoclient_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
static void tcp_echoclient_connection_close(struct tcp_pcb *tpcb, struct echoclient * es);
static err_t tcp_echoclient_poll(void *arg, struct tcp_pcb *tpcb);
static err_t tcp_echoclient_sent(void *arg, struct tcp_pcb *tpcb, u16_t len);
static void tcp_echoclient_send(struct tcp_pcb *tpcb, struct echoclient * es);
static err_t tcp_echoclient_connected(void *arg, struct tcp_pcb *tpcb, err_t err);
而TCP Server则有7个那么多.
static err_t tcp_echoserver_accept(void *arg, struct tcp_pcb *newpcb, err_t err);
static err_t tcp_echoserver_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
static void tcp_echoserver_error(void *arg, err_t err);
static err_t tcp_echoserver_poll(void *arg, struct tcp_pcb *tpcb);
static err_t tcp_echoserver_sent(void *arg, struct tcp_pcb *tpcb, u16_t len);
static void tcp_echoserver_send(struct tcp_pcb *tpcb, struct tcp_echoserver_struct *es);
static void tcp_echoserver_connection_close(struct tcp_pcb *tpcb, struct tcp_echoserver_struct *es);
形象地说,TCP模拟成一个教室的通信,而TCP Server时候,你就是老师,而TCP Client时候,你就是学生,老师可以接受很多学生提问,也可以给单独一个学生说话,也可以群体发话,学生之间不能之间聊天,只能跟老师说话.TCP Server和TCP Client可以共存在一个板子上,他们端口肯定是不一样的.如果是TCP Server,老师,只要知道课室是哪个,就能找到学生,而学生要找老师,就得跟着老师去了哪个课室,这样,是不是挺好理解的.
我们用官方的例子,但是进行一些分析.首先是创建一个老师啊.
void tcp_echoserver_init(void)
{tcp_echoserver_pcb = tcp_new();if (tcp_echoserver_pcb != NULL){err_t err;err = tcp_bind(tcp_echoserver_pcb, IP_ADDR_ANY, 7); /* TCP绑定 */if (err == ERR_OK){tcp_echoserver_pcb = tcp_listen(tcp_echoserver_pcb); /* 开始监听(等学生来) */tcp_accept(tcp_echoserver_pcb, tcp_echoserver_accept); /* 如果有什么动静,需要通知我,这个函数. */}}
}
然后再生成回调:
static err_t tcp_echoserver_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
{ if (es != NULL) { /* 当收到数据时 */ tcp_recv(newpcb, tcp_echoserver_recv); /* 当出错时 */ tcp_err(newpcb, tcp_echoserver_error); /* 当轮询时 */ tcp_poll(newpcb, tcp_echoserver_poll, 1); ret_err = ERR_OK; }
}
对于收到数据的处理方法:
static err_t tcp_echoserver_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{/* 空TCP数据 */if (p == NULL){ret_err = ERR_OK;}/* 非空但是数据不正确 */else if(err != ERR_OK){ret_err = err;}/* 连接成功 */else if(es->state == ES_ACCEPTED){ret_err = ERR_OK;}/* 收到数据 */else if (es->state == ES_RECEIVED){ret_err = ERR_OK;}/* 连接关闭后还能收到数据 */else{ret_err = ERR_OK;}return ret_err;
}
然后这个其实只需要tcp_echoserver_init,后续就一切可以了.一直监听,如果有数据,就会进入处理流程.
如果我们作为Client,就不断的发送新数据给老师(服务器).所以要知道老师的地址.所以,连接时候不一样,其他逻辑基本一样.
void tcp_echoclient_connect(void){ struct ip_addr DestIPaddr; /* create new tcp pcb */ echoclient_pcb = tcp_new(); if (echoclient_pcb != NULL) { IP4_ADDR( &DestIPaddr, DEST_IP_ADDR0, DEST_IP_ADDR1, DEST_IP_ADDR2, DEST_IP_ADDR3 ); /* connect to destination address/port */ tcp_connect(echoclient_pcb,&DestIPaddr,DEST_PORT,tcp_echoclient_connected); } else { /* deallocate the pcb */ memp_free(MEMP_TCP_PCB, echoclient_pcb);#ifdef SERIAL_DEBUG printf("\r can not create tcp pcb");#endif }}
其他都是一样的,那么,对于TCP的高级应用,TCP Web,就没什么难度了,就不多说了.例程:
DP83848以太网测试_TCP传输