LWIP socket 编程非阻塞模式

本文介绍了如何在单片机中优化socket编程,通过使用select函数和ioctlsocket设置非阻塞模式,减少任务浪费,提高内存资源利用率,特别是针对accept、send和recv等函数的非阻塞处理方式。

socket编程一般都是阻塞模式,例如accept函数,connect函数,send函数,recv函数。这些函数都是阻塞模式,对于单片机来说,阻塞模式处理起来需要浪费一个任务,如果这几个函数是阻塞模式,那么需要再其他任务做超时和异常处理。显然会浪费任务数量,对于本来就不多的单片机内存资源就是雪上加霜。那么必须设置位非阻塞态。让函数立即返回。如果出错直接执行出错路径。
方法1. 使用select函数和recv函数进行配合。
例如接收函数代码如下:

int eth_read(int fd,char *buf,int len,int time_out)
{
    fd_set rfd;
    struct timeval tv;
	int nfd = 0;
	
	tv.tv_usec = 00;
	tv.tv_sec = 1;

    FD_ZERO(&rfd);

	FD_SET(fd,&rfd);
	
	nfd = select(fd + 1,&rfd, NULL,  NULL, &tv);	

	if(nfd < 0)
	{
		return -1;
	}
	else if(nfd == 0)
	{
		return 0;
	}
	else
	{
		nfd = read(fd,buf,len);	
	}
	return nfd;	
}
int eth_write(int fd,char *buf,int len,int time_out)
{
	fd_set wfd;
	struct timeval tv;
	int nfd = 0;

	tv.tv_usec = 00;
	tv.tv_sec = 1;

	FD_ZERO(&wfd);

	FD_SET(fd,&wfd);

	nfd = select(fd + 1, NULL, &wfd, NULL, &tv);	

	if(nfd < 0)
	{
		return -1;
	}
	else if(nfd == 0)
	{
		return 0;
	}
	else
	{
		nfd = write(fd,buf,len);	
	}
    nfd = lwip_send(fd,buf,len,MSG_DONTWAIT);
	return nfd;
}

方法2.使用 ioctlsocket函数设置非阻塞模式
代码如下:

    int creat_socket(int protocl)
    {
	    int block = 1;
	    int comm_tick = 0;
	    int sockfd= socket(AF_INET6, SOCK_STREAM, 0);
	    if(sockfd , 0)
	    {
	    	return -1;
	    }
	    ioctlsocket(sockfd,FIONBIO,&block);  
	    return sockfd;
    }

后续的accept函数 send ,recv,connect 函数都是非阻塞模式。方便应用层处理。

<think>好的,我需要帮助用户找到关于使用lwIP进行TCP服务器编程的示例和教程。首先,我应该回忆一下lwIP的相关知识。lwIP是一个轻量级的TCP/IP协议栈,常用于嵌入式系统。用户需要的是如何建立一个TCP服务器的具体例子和教程。 接下来,我需要考虑用户可能的背景。他们可能是在嵌入式环境中工作,比如使用FreeRTOS或者uC/OS-II,或者在没有操作系统的裸机环境下编程。不同的环境配置lwIP的方式可能不同,因此需要涵盖这两种情况。 首先,我应该介绍lwIP的基本概念和它支持的两种模式:裸机(无操作系统)和操作系统模式(如FreeRTOS)。然后,分步骤说明如何在这两种模式下设置TCP服务器。每个步骤需要详细说明,比如包含必要的头文件、定义端口号、创建结构体实例、绑定端口、监听连接、处理接收数据等。 另外,用户可能需要代码示例。虽然我无法直接提供完整的代码,但可以给出关键部分的伪代码或代码框架,比如回调函数的实现、主循环的结构等。同时,需要提到一些重要的函数,如tcp_new(), tcp_bind(), tcp_listen(), tcp_accept()等,并解释它们的作用。 然后,我需要考虑用户可能需要的参考资料,比如官方文档、示例代码库和社区资源。引用这些资源可以帮助用户进一步查找详细信息。例如,lwIP的官方文档和GitHub仓库,以及FreeRTOS和STMicroelectronics的示例代码。 此外,用户可能会有一些常见问题,比如如何处理并发连接、配置lwIP参数、调试网络问题等。提前预测这些问题并在回答中简要提及解决方案会更有帮助,比如使用多线程或非阻塞调用,调整内存池大小,使用调试工具等。 最后,生成相关问题,帮助用户深入理解主题。例如,如何优化lwIP性能,在RTOS中集成lwIP,调试TCP连接问题的方法,以及lwIP的安全性问题。 需要确保回答结构清晰,分步骤说明,并且引用相关的资料,如用户提供的引用中的示例可能涉及到编译和补丁应用,但可能与当前问题关联不大,因此主要依赖lwIP的官方文档和其他可靠资源。同时,保持语言简洁,使用中文,并遵循格式要求,如行内公式使用$...$,独立公式用$$...$$,但在这个问题中可能涉及较少的数学表达式,更多是代码和步骤说明。</think>### lwIP TCP服务器编程示例与教程 lwIP(轻型IP协议栈)是专为嵌入式系统设计的开源TCP/IP协议栈,支持TCP、UDP、IPv4/IPv6等协议。以下是搭建TCP服务器的关键步骤和示例: --- #### **1. 环境配置** lwIP支持两种模式: - **无操作系统(裸机)**:需手动实现线程管理和定时器更新。 - **操作系统模式**(如FreeRTOS):依赖操作系统API进行任务调度。 ```c // 包含头文件 #include "lwip/tcp.h" #include "lwip/opt.h" ``` --- #### **2. TCP服务器实现步骤** ##### **步骤1:定义端口与结构体** ```c #define TCP_PORT 8080 struct tcp_server_state { struct tcp_pcb *pcb; uint8_t buffer[1024]; }; ``` ##### **步骤2:创建TCP控制块** ```c struct tcp_pcb *tcp_pcb = tcp_new(); // 创建TCP协议控制块 tcp_bind(tcp_pcb, IP_ADDR_ANY, TCP_PORT); // 绑定任意IP与指定端口 tcp_listen(tcp_pcb); // 进入监听状态 ``` ##### **步骤3:设置连接回调函数** ```c tcp_accept(tcp_pcb, tcp_accept_callback); // 注册新连接回调 // 新连接回调示例 err_t tcp_accept_callback(void *arg, struct tcp_pcb *new_pcb, err_t err) { struct tcp_server_state *state = (struct tcp_server_state *)arg; state->pcb = new_pcb; tcp_recv(new_pcb, tcp_recv_callback); // 注册数据接收回调 return ERR_OK; } ``` ##### **步骤4:处理接收数据** ```c err_t tcp_recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { if (p != NULL) { pbuf_copy_partial(p, state->buffer, p->tot_len, 0); // 复制数据到缓冲区 tcp_write(tpcb, state->buffer, p->tot_len, TCP_WRITE_FLAG_COPY); // 回传数据 pbuf_free(p); // 释放pbuf内存 } return ERR_OK; } ``` --- #### **3. 运行与调试** - **裸机环境**:需在主循环中调用`sys_check_timeouts()`更新协议栈定时器。 - **操作系统环境**:通过任务调度自动处理。 --- #### **4. 参考资源** 1. **官方文档**: lwIP用户手册详细说明API和配置选项[^1]。 2. **GitHub示例**: [lwIP官方示例库](https://github.com/lwip-tcpip/lwip)提供`contrib/examples/tcpecho`代码。 3. **社区教程**: STM32或ESP32的硬件平台教程常包含lwIP实战案例[^2]。 --- ### 常见问题解答 - **Q: 如何支持多客户端并发连接?** A: 为每个新连接创建独立的`tcp_pcb`实例,并通过回调函数隔离状态。 - **Q: 如何配置lwIP内存池大小?** A: 修改`lwipopts.h`中的`MEMP_NUM_TCP_PCB`和`PBUF_POOL_SIZE`参数[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值