STM32F4-DISCO 学习之LWIP TCP学习

/ 0评 / 1

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,后续就一切可以了.一直监听,如果有数据,就会进入处理流程.

MCU作为TCP服务器

如果我们作为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("
 can not create tcp pcb");
#endif
  }
}

 其他都是一样的,那么,对于TCP的高级应用,TCP Web,就没什么难度了,就不多说了.例程:

DP83848以太网测试_TCP传输

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注