705|2

303

帖子

3

TA的资源

纯净的硅(高级)

 

【极海APM32F407 Tiny Board】lwip之tcp client通信 [复制链接]

  本帖最后由 TL-LED 于 2023-6-15 08:09 编辑

这篇来测试下是tcp client通信测试。

在上篇http://bbs.eeworld.com.cn/thread-1245099-1-1.html移植LWIP基础上,增加tcp clent通信的测试。

tcp client模式下,客户端程序主动发起连接请求,向服务器发送请求信息,并等待服务器响应。一旦建立连接成功,客户端和服务器就可以相互发送和接收数据。

 

一、硬件连接

开发板的网口和PC机,同处一个IP段,测试tcp client模式下的数据通信。

106.jpg

二、程序部分

2.1、echo.c

/** This file was modified by Geehy Semiconductor */

#include "lwip/opt.h"
#include "lwip/debug.h"
#include "lwip/stats.h"
#include "lwip/tcp.h"
#include "echo_c.h"
#include <stdlib.h>
#include <string.h>


#if LWIP_TCP

static struct tcp_pcb *tcpc_echo_pcb;

enum tcpc_echo_states
{
  ES_NONE = 0,
  ES_ACCEPTED,
  ES_RECEIVED,
  ES_CLOSING
};

struct tcpc_echo_state
{
  u8_t state;
  u8_t retries;
  struct tcp_pcb *pcb;
  /* pbuf (chain) to recycle */
  struct pbuf *p;
};

struct tcpc_echo_state * tcpc_echo_es;
uint8_t testdata[50] = "TCP Client to connect server";

err_t tcpc_echo_accept(void *arg, struct tcp_pcb *newpcb, err_t err);
err_t tcpc_echo_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
void tcpc_echo_error(void *arg, err_t err);
err_t tcpc_echo_poll(void *arg, struct tcp_pcb *tpcb);
err_t tcpc_echo_sent(void *arg, struct tcp_pcb *tpcb, u16_t len);
void tcpc_echo_send(struct tcp_pcb *tpcb, struct tcpc_echo_state *es);
void tcpc_echo_close(struct tcp_pcb *tpcb, struct tcpc_echo_state *es);
void PrintfRecData(struct pbuf *p);

/*!
 * @brief   tcp client init
 *
 * @param       tcpc_port£o client port
 *
 * @param       ipaddr£o point to the client ip address
 *
 * @retval      None
 */
void
tcpc_echo_init(ip_addr_t *ipaddr,uint16_t tcpc_port)
{
  tcpc_echo_pcb = tcp_new();
  if (tcpc_echo_pcb != NULL)
  {
    /* connect to server address£oport */
    tcp_connect(tcpc_echo_pcb,ipaddr,tcpc_port,tcpc_echo_accept);
  }
  else
  {
    /* abort? output diagnostic? */
  }
}

/*!
 * @brief       closes tcp client
 *
 * @param       None
 *
 * @retval      None
 */
void tcpc_echo_disable(void)
{
    tcpc_echo_close(tcpc_echo_pcb,tcpc_echo_es);
}

/*!
 * @brief       Printf TCP Receive Data
 *
 * @param       p: pointer on the tcp pcb received pbuf
 *
 * @retval      None
 */
void PrintfRecData(struct pbuf *p)
{
    char recbuf[100] = {0};

    memcpy(recbuf,p->payload,p->len);
    printf("received message:%s\r\n",recbuf);
}

/*!
 * @brief       LwIP tcp_accept callback function
 *
 * @param       newpcb: point to the newly created tcp pcb
 *
 * @retval      None
 */
err_t
tcpc_echo_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
{
  err_t ret_err;
  struct tcpc_echo_state *es;

  LWIP_UNUSED_ARG(arg);
  LWIP_UNUSED_ARG(err);

  /* Unless this pcb should have NORMAL priority, set its priority now.
     When running out of pcbs, low priority pcbs can be aborted to create
     new pcbs of higher priority. */
  tcp_setprio(newpcb, TCP_PRIO_MIN);

  es = (struct tcpc_echo_state *)mem_malloc(sizeof(struct tcpc_echo_state));
  tcpc_echo_es=es;

  if (es != NULL)
  {
    es->state = ES_ACCEPTED;
    es->pcb = newpcb;
    es->retries = 0;
    es->p = NULL;
    /* pass newly allocated es to our callbacks */
    tcp_arg(newpcb, es);
    tcp_recv(newpcb, tcpc_echo_recv);
    tcp_err(newpcb, tcpc_echo_error);
    tcp_poll(newpcb, tcpc_echo_poll, 0);

	/** Allocates the pbuf of the given type */
    es->p = pbuf_alloc(PBUF_TRANSPORT, strlen((char*)testdata) , PBUF_POOL);

    /** copy data to pbuf */
    pbuf_take(es->p, (char*)testdata, strlen((char*)testdata));

	/** send data */
    tcp_sent(newpcb, tcpc_echo_sent);
    tcpc_echo_send(newpcb,es);

    ret_err = ERR_OK;
  }
  else
  {
    /** close tcp connection */
    tcpc_echo_close(newpcb, es);
    ret_err = ERR_MEM;
  }
  return ret_err;
}

/*!
 * @brief       LwIP tcp_recv callback function
 *
 * @param       None
 *
 * @retval      None
 */
err_t
tcpc_echo_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
  struct tcpc_echo_state *es;
  err_t ret_err;

  LWIP_ASSERT("arg != NULL",arg != NULL);
  es = (struct tcpc_echo_state *)arg;
  if (p == NULL)
  {
    /* remote host closed connection */
    es->state = ES_CLOSING;
    if(es->p == NULL)
    {
       /* we're done sending, close it */
       tcpc_echo_close(tpcb, es);
    }
    else
    {
      /* we're not done yet */
      tcp_sent(tpcb, tcpc_echo_sent);
      tcpc_echo_send(tpcb, es);
    }
    ret_err = ERR_OK;
  }
  else if(err != ERR_OK)
  {
    /* cleanup, for unkown reason */
    if (p != NULL)
    {
      es->p = NULL;
      pbuf_free(p);
    }
    ret_err = err;
  }

  else if(es->state == ES_ACCEPTED)
  {
    tcp_recved(tpcb, p->tot_len);

    /** Printf TCP Receive Data */
    PrintfRecData(p);

    es->p = NULL;
    pbuf_free(p);
    ret_err = ERR_OK;
  }
  else
  {
    /* unkown es->state, trash data  */
    tcp_recved(tpcb, p->tot_len);
    es->p = NULL;
    pbuf_free(p);
    ret_err = ERR_OK;
  }
  return ret_err;
}

/*!
 * @brief       LwIP tcp_err callback function
 *
 * @param       None
 *
 * @retval      None
 */
void
tcpc_echo_error(void *arg, err_t err)
{
  struct tcpc_echo_state *es;

  LWIP_UNUSED_ARG(err);

  es = (struct tcpc_echo_state *)arg;
  if (es != NULL)
  {
    mem_free(es);
  }
}

/*!
 * @brief       LwIP tcp_poll callback function
 *
 * @param       None
 *
 * @retval      None
 */
err_t
tcpc_echo_poll(void *arg, struct tcp_pcb *tpcb)
{
  err_t ret_err;
  struct tcpc_echo_state *es;

  es = (struct tcpc_echo_state *)arg;
  if (es != NULL)
  {
    if (es->p != NULL)
    {
      /* there is a remaining pbuf (chain)  */
      tcp_sent(tpcb, tcpc_echo_sent);
      tcpc_echo_send(tpcb, es);
    }
    else
    {
      /* no remaining pbuf (chain)  */
      if(es->state == ES_CLOSING)
      {
        tcpc_echo_close(tpcb, es);
      }
    }
    ret_err = ERR_OK;
  }
  else
  {
    /* nothing to be done */
    tcp_abort(tpcb);
    ret_err = ERR_ABRT;
  }
  return ret_err;
}

/*!
 * @brief       LwIP tcp_sent callback function
 *
 * @param       None
 *
 * @retval      None
 */
err_t
tcpc_echo_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
{
  struct tcpc_echo_state *es;

  LWIP_UNUSED_ARG(len);

  es = (struct tcpc_echo_state *)arg;
  es->retries = 0;

  if(es->p != NULL)
  {
    /* still got pbufs to send */
    tcp_sent(tpcb, tcpc_echo_sent);
    tcpc_echo_send(tpcb, es);
  }
  else
  {
    /* no more pbufs to send */
    if(es->state == ES_CLOSING)
    {
      tcpc_echo_close(tpcb, es);
    }
  }
  return ERR_OK;
}

/*!
 * @brief       tcp send data function
 *
 * @param       tpcb: point to the tcp pcb
 *
 * @param       es: point to tcps_echo_state structure
 *
 * @retval      None
 */
void
tcpc_echo_send(struct tcp_pcb *tpcb, struct tcpc_echo_state *es)
{
  struct pbuf *ptr;
  err_t wr_err = ERR_OK;

  while ((wr_err == ERR_OK) &&
         (es->p != NULL) &&
         (es->p->len <= tcp_sndbuf(tpcb)))
  {
  ptr = es->p;

  /* enqueue data for transmission */
  wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1);
  if (wr_err == ERR_OK)
  {
     //u16_t plen;
      u8_t freed;

     //plen = ptr->len;
     /* continue with next pbuf in chain (if any) */
     es->p = ptr->next;
     if(es->p != NULL)
     {
       /* new reference! */
       pbuf_ref(es->p);
     }
     /* chop first pbuf from chain */
      do
      {
        /* try hard to free pbuf */
        freed = pbuf_free(ptr);
      }
      while(freed == 0);
      // /* we can read more data now */
      // tcp_recved(tpcb, plen);
   }
   else if(wr_err == ERR_MEM)
   {
      /* we are low on memory, try later / harder, defer to poll */
     es->p = ptr;
   }
   else
   {
     /* other problem ?? */
   }
  }
}

/*!
 * @brief       closes tcp pcb function
 *
 * @param       tpcb: point to the tcp pcb
 *
 * @param       es: point to tcps_echo_state structure
 *
 * @retval      None
 */
void
tcpc_echo_close(struct tcp_pcb *tpcb, struct tcpc_echo_state *es)
{
  tcp_arg(tpcb, NULL);
  tcp_sent(tpcb, NULL);
  tcp_recv(tpcb, NULL);
  tcp_err(tpcb, NULL);
  tcp_poll(tpcb, NULL, 0);

  if (es != NULL)
  {
    mem_free(es);
  }
  tcp_close(tpcb);
}

#endif /* LWIP_TCP */

2.2、echo.h

#ifndef __ECHO_H__
#define __ECHO_H__

#include "main.h"

void tcpc_echo_init(ip_addr_t *ipaddr,uint16_t tcpc_port);
void tcpc_echo_disable(void);

#endif /* __MINIMAL_ECHO_H */

2.3、main.c

#include "main.h"
#include "Board.h"
#include "oled.h"
#include "stdio.h"
#include "usart.h"
#include "echo_c.h"

/** Global pointers on Rx descriptor used to transmit and receive descriptors */
extern ETH_DMADescConfig_T  *DMARxDescToGet;

/** current Ethernet LocalTime value */
volatile uint32_t ETHTimer = 0;
/** lwip network interface structure for ethernetif */
struct netif UserNetif;

/** TCP periodic Timer */
uint32_t TCPTimer = 0;
/** ARP periodic Timer */
uint32_t ARPTimer = 0;
/** MAC address */
uint8_t SetMACaddr[6] = {0,0,0,0,0,8};

int main(void)
{
	ip4_addr_t destipaddr;
	SysTick_Init();
	init_led();
	init_usart();
	ConfigEthernet();
	LwIP_Init();
	led2_off();
	led3_on();
	IP4_ADDR(&destipaddr, 192, 168, 1, 112);
	tcpc_echo_init(&destipaddr,5000);
	printf("server ip : %d.%d.%d.%d :%d  \r\n",192,168,1,112,5000);
	while (1)
	{

		/** check if any packet received */
			if (ETH_ReadRxPacketSize(DMARxDescToGet))
			{
					/** process received ethernet packet */
					LwIP_Pkt_Handle();
			}
					/** handle periodic timers for LwIP */
			LwIP_Periodic_Handle(ETHTimer);
	}
}

void LwIP_Init(void)
{
	ip4_addr_t ipaddr;
	ip4_addr_t netmask;
	ip4_addr_t gw;

    /** Initializes the dynamic memory heap */
    mem_init();

    /** Initializes the memory pools */
    memp_init();

    IP4_ADDR(&ipaddr, 192, 168, 1, 22);
    IP4_ADDR(&netmask, 255, 255 , 255, 0);
    IP4_ADDR(&gw, 192, 168, 1, 1);

    /** Config MAC Address */
    ETH_ConfigMACAddress(ETH_MAC_ADDRESS0, SetMACaddr);

    /** Add a network interface to the list of lwIP netifs */
    netif_add(&UserNetif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, ðernet_input);

    /** Registers the default network interface */
    netif_set_default(&UserNetif);

    /** When the netif is fully configured this function must be called */
    netif_set_up(&UserNetif);

    /** Use Com printf static IP address*/
    printf("\n  Static IP address   \r\n");
    printf("IP: %d.%d.%d.%d\r\n",192,168,1,22);
    printf("NETMASK: %d.%d.%d.%d\r\n",255,255,255,0);
    printf("Gateway: %d.%d.%d.%d\r\n",192,168,1,1);
}

/*!
 * @brief       This function received ethernet packet
 *
 * @param       None
 *
 * @retval      None
 */
void LwIP_Pkt_Handle(void)
{
  /** Read a received packet from the Ethernet buffers and send it to the lwIP for handling */
  ethernetif_input(&UserNetif);
}

/*!
 * @brief       This function LwIP periodic tasks
 *
 * @param       ETHTimer the current Ethernet Timer value
 *
 * @retval      None
 */
void LwIP_Periodic_Handle(__IO uint32_t ETHTimer)
{
#if LWIP_TCP
    /** TCP periodic process every 250 ms */
    if (ETHTimer - TCPTimer >= TCP_TMR_INTERVAL)
    {
        TCPTimer =  ETHTimer;
        tcp_tmr();
    }
#endif

    /** ARP periodic process every 5s */
    if ((ETHTimer - ARPTimer) >= ARP_TMR_INTERVAL)
    {
        ARPTimer =  ETHTimer;
        etharp_tmr();
    }
}

 

三、程序运行

3.1、打开调试助手,设置tcp server模式

102.png

3.2、复位开发板,上电后,自动连接服务器,串口调试助手发送数据,开发板串口输出接收的信息。

107.png

 

四、工程文件

apm32f407i_prj.rar (11.14 MB, 下载次数: 1)

最新回复

能把工程发一下我吗?我的网络调试不通,着急啊   详情 回复 发表于 2023-6-14 21:10
 
 
 

回复
举报

263

帖子

0

TA的资源

一粒金砂(高级)

 

能把工程发一下我吗?我的网络调试不通,着急啊

点评

好的,我已经上传到帖子里了。  详情 回复 发表于 2023-6-15 08:10
个人签名

gitee/casy

 
 
 

回复

303

帖子

3

TA的资源

纯净的硅(高级)

 
caizhiwei 发表于 2023-6-14 21:10 能把工程发一下我吗?我的网络调试不通,着急啊

好的,我已经上传到帖子里了。

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表