野火挑战者V2 STM32F429IGT6开发板TCP服务端通信实现

  • Post author:
  • Post category:其他


在上一篇推文 野火挑战者V2 STM32F429IGT6开发板TCP客户端通信实现

https://mp.csdn.net/mp_blog/creation/editor/127216854

的基础上进行如下改变

1、在工程中添加 tcpserver.c、tcpserver.h 两个文件,代码如下:

tcpserver.c

#include "tcpserver.h"
#include "lwip/netif.h"
#include "lwip/ip.h"
#include "lwip/tcp.h"
#include "lwip/init.h"
#include "netif/etharp.h"
#include "lwip/udp.h"
#include "lwip/pbuf.h"
#include <stdio.h>	
#include <string.h>

static err_t tcpecho_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
  if (p != NULL) 
  {        
		/* 更新窗口*/
		tcp_recved(tpcb, p->tot_len);
					
		/* 返回接收到的数据*/  
		tcp_write(tpcb, p->payload, p->tot_len, 1);
			
		memset(p->payload, 0 , p->tot_len);
		pbuf_free(p);
    
  } 
  else if (err == ERR_OK) 
  {
    return tcp_close(tpcb);
  }
  return ERR_OK;
}

static err_t tcpecho_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
{     
	uint8_t XZ[]={"This is a TCP Server test...\n"};
	
  tcp_recv(newpcb, tcpecho_recv);
	
	tcp_write(newpcb, XZ, sizeof(XZ), 1);
	
  return ERR_OK;
}

void TCP_Server_Init(void)
{
  struct tcp_pcb *pcb = NULL;	            		
  
  /* 创建一个TCP控制块  */
  pcb = tcp_new();	  
  
  /* 绑定TCP控制块 */
  tcp_bind(pcb, IP_ADDR_ANY, TCP_ECHO_PORT);       


  /* 进入监听状态 */
  pcb = tcp_listen(pcb);				

  /* 处理连接 */	
  tcp_accept(pcb, tcpecho_accept);   
}

tcpclient.h

#ifndef _TCPSERVER_H_
#define _TCPSERVER_H_

#define TCP_ECHO_PORT 5001

void TCP_Server_Init(void);

#endif


2、在main.c中添加头文件 #include “tcpserverh” 以及在 main函数的wahile(1) 以前添加 TCP_Server_Init(); 语句。

编译工程,烧录到开发板中,在ping通开发板以后,打开网络调试助手。网络调试助手创建TCP客户端,随后连接,IP地址和端口 要和代码中的对应。如图:




到这里可以看到电脑上的TCP客户端已经连接上了开发板的TCP服务端,并且接受到了服务端发送的消息:This is a TCP Server test…而这句话就是在 tcpserver.c代码的 tcpecho_accept 函数中。该函数在 tcp_accept 中被调用,只要有客户端成功连接上开发板就会发送该语句。

在网络调试助手的输入框中输入1234,然后点击发送数据可以看到数据接收窗口有如下变化:

这是在tcpserver.c 代码的 tcpecho_recv函数中 有如下代码:

tcp_write(tpcb, p->payload, p->tot_len, 1);

memset(p->payload, 0 , p->tot_len);

pbuf_free(p);

这段代码的作用就是在接收到LWIP的内容后再将该内容写入到LWIP的tpcb控制块的发送寄存器中,然后通过LWIP发送出去。如果我们需要进行其他操作只需要修改这几条语句即可。

在此基础上稍微做如下修改:

在tcpclient.c 文件开头添加如下代码:

unsigned char TCP_Rrcrive_Date[255];

unsigned int TCP_Rrcrive_length = 0;

在 tcpclient.c 代码的 tcpecho_recv 函数修改成如下语句:

static err_t tcpecho_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
  if (p != NULL) 
  {        
		/* 更新窗口*/
		tcp_recved(tpcb, p->tot_len);
			
		TCP_Rrcrive_length = p->tot_len;
		memcpy(TCP_Rrcrive_Date,p->payload,TCP_Rrcrive_length);
		
		/* 返回接收到的数据*/  
		tcp_write(tpcb, p->payload, p->tot_len, 1);
			
		memset(p->payload, 0 , p->tot_len);
		pbuf_free(p);
		
		printf("%s\n",TCP_Rrcrive_Date);
    
  } 
  else if (err == ERR_OK) 
  {
    return tcp_close(tpcb);
  }
  return ERR_OK;
}

修改后的代码可以将TCP接收的来自LWIP的数据储存在一个全局变量数组TCP_Rrcrive_Date中,同时还将数据长度储存在TCP_Rrcrive_length中,最后再通过串口将接收的消息以字符串的格式打印出来。

这里只是简单的演示下对接收数据的处理,事实上我们完全可以自己编写一个服务端数据处理函数,自定义自己的通信协议,进而实现不同的功能。



版权声明:本文为qq_44712722原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。