欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ESP8266 TCP客户端代码(自动连接,断开识别)

程序员文章站 2024-03-23 09:40:34
...

user_socket.c

#include "user_socket.h"



//===================================================================
//							变量定义
//===================================================================
int tcp_fd = -1;




/********************************************************************
 *@brief	发送TCP数据
 *@param[in] buffer
 *@param[in] size
 *@return	 <0失败	成功时返回已发送的长度
 *******************************************************************/
int user_socket_tcp_send(const void *buffer, size_t size)
{
	if(tcp_fd < 0 || buffer == NULL || size <= 0)
	{
		return -1;
	}

	return send(tcp_fd,buffer,size,0);
}


/********************************************************************
 *@brief	TCP连接
 *@param[in] none
 *@return	 <0失败	成功时返回fd
 *******************************************************************/
int user_socket_tcp_connect(void)
{
	int fd;
	int tmp;
	struct sockaddr_in addr;
	memset((char*)&addr,0,sizeof(addr));

	addr.sin_family 	 = AF_INET;
	addr.sin_port 		 = htons(USER_TCP_PORT);
	addr.sin_addr.s_addr = inet_addr(USER_TCP_IP);

	fd = socket(AF_INET, SOCK_STREAM, 0);
	if(fd < 0)
	{
		printf("tcp socket fail\n");
		return -1;
	}

	//开启keepalive属性
	tmp = 1;
	if(setsockopt(fd, SOL_SOCKET,SO_KEEPALIVE,&tmp,sizeof(tmp)) < 0)
	{
		printf("tcp set SO_KEEPALIVE fail\n");
	}

	//如该连接在10秒内没有任何数据往来,则进行探测
	tmp = 10;
	if(setsockopt(fd, IPPROTO_TCP,TCP_KEEPIDLE,&tmp,sizeof(tmp))<0)
	{
		printf("tcp set TCP_KEEPIDLE fail\n");
	}

	//探测时发包的时间间隔为2秒
	tmp = 2;
	if(setsockopt(fd, IPPROTO_TCP,TCP_KEEPINTVL,&tmp,sizeof(tmp))<0)
	{
		printf("tcp set TCP_KEEPINTVL fail\n");
	}

	//探测尝试的次数.如果第1次探测包就收到响应了,则后几次的不再发
	tmp = 3;
	if(setsockopt(fd, IPPROTO_TCP,TCP_KEEPCNT,&tmp,sizeof(tmp))<0)
	{
		printf("tcp set TCP_KEEPCNT fail\n");
	}

	//开始连接tcp
	if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
	{
		close(fd);
		printf("tcp connect fail\n");
		return -1;
	}

	printf("tcp connect ok!\n");

	return fd;
}



/********************************************************************
 *@brief	TCP任务
 *@param[in] pvParameters
 *@return	 none
 *******************************************************************/
static void user_socket_tcp_task(void *pvParameters)
{
	printf("%s\n",__func__);

	//申请TCP接收buff内存
	uint8_t *tcp_rx_buff = NULL;
	if((tcp_rx_buff = (uint8_t*)os_malloc(USER_TCP_RX_BUFF_MAX)) == NULL)
	{
		printf("failed to allocate memory\r\n");
		goto	user_socket_tcp_task_exit;
	}


	tcp_fd = -1;
	int    ufd,maxfd;
	fd_set rset;
	struct timeval 		timeout;
	struct sockaddr_in  addr;
	memset((char*)&addr,0,sizeof(addr));

	addr.sin_family 	 = AF_INET;
	addr.sin_port   	 = htons(10000);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);

	ufd = socket(AF_INET, SOCK_DGRAM, 0);

	if(ufd < 0)
	{
		printf("create udp socket fail\n");
	}

	bind(ufd, (struct sockaddr*)&addr, sizeof(addr));

	maxfd = ufd;

	//清空socket集合
	FD_ZERO(&rset);


	while(1)
	{
		//wifi没有连接成功,或者还没有获取到IP
		if(wifi_station_get_connect_status() != STATION_GOT_IP)
		{
			vTaskDelay(100/portTICK_RATE_MS);
			continue;
		}

		//是否socket没有连接
		if(tcp_fd < 0)
		{
			//尝试连接socket
			if((tcp_fd = user_socket_tcp_connect()) < 0)
			{
				vTaskDelay(500/portTICK_RATE_MS);
				continue;
			}
		}

		maxfd = ufd;
		if(maxfd < tcp_fd)
		{
			maxfd = tcp_fd;
		}

		//清空socket集合
		FD_ZERO(&rset);

		if(tcp_fd >= 0)
		{
			//加入已连接的socket到集合
			FD_SET(tcp_fd,&rset);
		}

		FD_SET(ufd,&rset);

		timeout.tv_sec  = 3;	//秒
		timeout.tv_usec = 0;	//微秒
		//在此函数最大等待timeout.tv_sec秒,如果有收到数据就立即退出此函数。
		if(select(maxfd+1, &rset, NULL, NULL, &timeout) <= 0)
		{
			continue;
		}


		//检查tcp_fd是否在这个集合里面
		if (FD_ISSET(tcp_fd, &rset))
		{
			int read_length;

			//TCP接收数据处理
			if((read_length = recv(tcp_fd,tcp_rx_buff,USER_TCP_RX_BUFF_MAX,0)) > 0)
			{
				printf("fd read_buff data bytes:%d\r\n",read_length);
				USER_LOG_HEXDUMP(tcp_rx_buff,read_length);
			}
			else
			{
				close(tcp_fd);
				tcp_fd = -1;

				printf("tcp disconnectd!\r\n");
			}
		}
		//检查ufd是否在这个集合里面
		else if(FD_ISSET(ufd,&rset))
		{
			int alen = sizeof(struct sockaddr_in);

			int read_length;
			if((read_length=recvfrom(ufd,tcp_rx_buff,USER_TCP_RX_BUFF_MAX,0,(struct sockaddr*)&addr,(socklen_t*)&alen)) > 0)
			{
				printf("ufd read_buff data bytes:%d\r\n",read_length);
				USER_LOG_HEXDUMP(tcp_rx_buff,read_length);
			}
		}
	}

user_socket_tcp_task_exit:
	if(tcp_rx_buff != NULL)  aos_free(tcp_rx_buff);

	vTaskDelete(NULL);
}





/********************************************************************
 *@brief	 tcp初始化
 *@param[in] none
 *@return	 none
 *******************************************************************/
void user_socket_tcp_init(void)
{
    xTaskCreate(user_socket_tcp_task, "", 256, NULL, 4, NULL);
}










user_socket.h

#ifndef __USER_SOCKET_H__
#define __USER_SOCKET_H__

#include "esp_common.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "lwip/sockets.h"


//===================================================================
//							常量定义
//===================================================================
#define	USER_TCP_IP					"192.168.46.108"
#define	USER_TCP_PORT				8080
#define USER_TCP_RX_BUFF_MAX		256





//===================================================================
//							函数声明
//===================================================================
static void user_socket_tcp_task(void *pvParameters);
int user_socket_tcp_send(const void *buffer, size_t size);
void user_socket_tcp_init(void);
#endif

使用说明:

        1、在user_init函数中调用user_socket_tcp_init创建tcp任务

        2、WIFI连接成功之后,会自动进行TCP连接,tcp连接成功时打印 tcp connect ok!。tcp断开连接时打印tcp disconnectd!。收到tcp数据时打印fd read_buff data bytes。

        3、’用户发送tcp数据时调用user_socket_tcp_send

上一篇: Mac安装sumo

下一篇: SUMO简单使用