LWIP+TCP客户端

一、TCP API函数

其中tcp_poll()函数的第三个参数表示隔几秒调用一次这个周期性函数

二、修改服务器的IP

三、TCP客户端编程思路

  1. 申请套接字
  2. 绑定服务器IP和端口号
  3. 等待客户端连接 进入连接回调函数
  4. 在连接回调函数中 配置一些回调函数,如接收回调函数,周期回调函数等等(类似于QT里面的信号与槽机制,等待一个信号的来临,然后执行对应的函数)
  5. 在接收回调函数里面将 接收的消息发送给客户端

四、完整代码

tcp_client.c

#include "tcp_client.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define IP0 192
#define IP1 168
#define IP2 1
#define IP3 104

#define PORT 8080

int Tcp_Client_Init(void)
{
	struct tcp_pcb *tcp_client_pcb;
	struct ip_addr ipaddr;

	tcp_client_pcb = tcp_new();//为tcp客户端分配一个tcp_pcb结构体
	
	if(tcp_client_pcb)//创建成功
	{
		IP4_ADDR(&ipaddr, IP0, IP1, IP2, IP3);
		
		//连接到目的地址的指定端口上,当连接成功后回调tcp_client_connected()函数
		tcp_connect(tcp_client_pcb, &ipaddr, PORT, tcp_client_connected);
		
		return 0;//初始化成功
	}
	return 1;//初始化失败
}

//lwIP TCP连接建立后调用回调函数
static err_t tcp_client_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{
	struct tcp_client_struct *es=NULL;  
	
	if(err==ERR_OK)   
	{
		//建立连接后发送一个connect success 信息
		tcp_write(pcb, "STM32F407 connect success \r\n", strlen("STM32F407 connect success \r\n"), 1);
		
		es=(struct tcp_client_struct*)malloc(sizeof(struct tcp_client_struct)); 
		es->state=ES_TCPCLIENT_CONNECTED;//状态为连接成功
		es->pcb=pcb;  
		es->p=NULL; 
		
		//更新tpcb所有回调函数的参数arg。pcb:当前TCP连接的控制块、es:需要传递给回调函数的参数
		tcp_arg(pcb,es);        			
		
		//配置接收回调函数
		tcp_recv(pcb, tcp_client_recv);
		
		//配置回调函数,该函数周期性调用,每隔一秒调用一次
		tcp_poll(pcb,tcp_client_poll,1);     			
	}
	else
	{
		return tcp_close(pcb);
	}
	return ERR_OK;
}

//lwIP tcp_recv()函数的回调函数
static err_t tcp_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *tcp_recv_pbuf, err_t err)
{
	struct pbuf *tcp_send_pbuf;
	struct tcp_client_struct *es = (struct tcp_client_struct *)arg;

	//TCP客户端处于连接状态  且  接收到的数据不为空时
	if (es->state==ES_TCPCLIENT_CONNECTED && tcp_recv_pbuf != NULL)
	{
		// 扩大收发数据的窗口
		tcp_recved(pcb, tcp_recv_pbuf->tot_len);

		// 将接收的数据拷贝给发送结构体 
		tcp_send_pbuf = tcp_recv_pbuf;

		// 将接收到的数据再转发出去,最后一个参数为1,表示立即发送数据;0表示将数据放入发送缓冲区,等待下一个发送事件再发送。
		tcp_write(pcb, tcp_send_pbuf->payload, tcp_send_pbuf->len, 1);

		pbuf_free(tcp_recv_pbuf);
	}
	else if (err != ERR_OK)
	{
		if(es)
		{
			free(es);
			es=NULL;
		}
		if(tcp_recv_pbuf)
		{
			pbuf_free(tcp_recv_pbuf);//释放接收pbuf
			tcp_recv_pbuf=NULL;
		}
		return tcp_close(pcb);
	}
	return ERR_OK;
}

//lwIP tcp_poll的回调函数
err_t tcp_client_poll(void *arg, struct tcp_pcb *tpcb)
{
	err_t ret_err;
	struct tcp_client_struct *es = (struct tcp_client_struct*)arg;
	if(es!=NULL)  //连接处于空闲可以发送数据
	{
		
	}
	return ret_err;
} 

tcp_client.h

#ifndef __TCP_CLIENT_T
#define __TCP_CLIENT_T

#include "lwip/debug.h"
#include "lwip/stats.h"
#include "lwip/tcp.h"
#include "lwip/memp.h"
#include "lwip/mem.h"
#include "lwip_comm.h"


//tcp服务器连接状态
enum tcp_client_states
{
	ES_TCPCLIENT_NONE = 0,		//没有连接
	ES_TCPCLIENT_CONNECTED,		//连接到服务器了 
	ES_TCPCLIENT_CLOSING,		//关闭连接
}; 

//LWIP回调函数使用的结构体
struct tcp_client_struct
{
	u8 state;//当前连接状态
	struct tcp_pcb *pcb;    //指向当前的pcb
	struct pbuf *p;         //指向接收/或传输的pbuf
};  

int Tcp_Client_Init(void);
static err_t tcp_client_connected(void *arg, struct tcp_pcb *pcb, err_t err);
static err_t tcp_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *tcp_recv_pbuf, err_t err);
err_t tcp_client_poll(void *arg, struct tcp_pcb *tpcb);
void tcp_client_close_connection(struct tcp_pcb *tpcb);


#endif


五、注意事项

如果出现客户端连接不上的情况,可以看看是否可以ping通,如果ping的过程中出现TTL传输中过期,可以尝试将以太网禁用然后启用,在等待一定的时间,看是否可以连接成功。

相关推荐

  1. ZooKeeper客户实战

    2024-05-04 13:10:05       29 阅读
  2. Kafka客户实战

    2024-05-04 13:10:05       31 阅读
  3. 游戏客户开发

    2024-05-04 13:10:05       20 阅读
  4. Docker客户命令

    2024-05-04 13:10:05       13 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-05-04 13:10:05       15 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-04 13:10:05       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-04 13:10:05       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-04 13:10:05       18 阅读

热门阅读

  1. Centos 启动jar包的详细步骤

    2024-05-04 13:10:05       9 阅读
  2. nginx在CentOS系统安装

    2024-05-04 13:10:05       9 阅读
  3. VM Ubuntu unknown filesystem

    2024-05-04 13:10:05       14 阅读
  4. 综合案例(账号密码登录和SQL注入)

    2024-05-04 13:10:05       11 阅读
  5. 我的创作纪念日

    2024-05-04 13:10:05       10 阅读
  6. 批处理任务的通用工具类

    2024-05-04 13:10:05       9 阅读
  7. git简介

    git简介

    2024-05-04 13:10:05      8 阅读
  8. 【Trick】conda指令安装yml文件中的python依赖

    2024-05-04 13:10:05       11 阅读
  9. 纯正英语新闻 5.7(提前)

    2024-05-04 13:10:05       9 阅读