【lwip】第二篇:使用lwip的netconn接口编写TCP服务器

一、netconn介绍

  参考链接:https://lwip.fandom.com/wiki/Netconn_API
  netconn API 是一个顺序API,旨在使lwip协议栈更易于使用(与事件驱动的原始 API 相比),同时仍保留零拷贝功能。
  要使用netconnAPI,需要一个操作系统,因为这个API需要使用线程。协议栈核心中的所有数据包处理(输入和输出)都是在一个专用线程内完成的-Tcpip线程)。应用程序线程使用邮箱和信号量与此专用线程通信。

二、netconn API

/*
创建netconn
t:netconn的类型,可取
  NETCONN_TCP       
  NETCONN_UDP       
  NETCONN_UDPLITE  
  NETCONN_UDPNOCHKSUM
  NETCONN_RAW 
返回:netconn句柄
*/
#define netconn_new(t)                  netconn_new_with_proto_and_callback(t, 0, NULL)
struct netconn* netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback)

/*
删除netconn
conn:netconn句柄
*/
err_t   netconn_delete(struct netconn *conn);
/*
获得netconn的ip和端口
conn:netconn句柄
addr:保存获取的ip
port:保存获取的端口
local:为1时获取本地地址、为1时获取远端地址
*/
err_t   netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local);

/*
绑定本地ip地址到netconn
conn:netconn句柄
addr:本地ip
port:本地端口
*/
err_t   netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port);
/*
连接到远端ip和端口
conn:客户端本地ip
port:客户端本地端口
*/
err_t   netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port);
/*
仅可用于UDP,断开连接
conn:netconn句柄
*/
err_t   netconn_disconnect (struct netconn *conn);

/*
将tcp的连接切换成listen模式
conn:netconn句柄
*/
#define netconn_listen(conn) netconn_listen_with_backlog(conn, TCP_DEFAULT_LISTEN_BACKLOG)
/*
tcp服务器获取新建立的连接,也就是监听到的连接
conn:旧的连接
new_conn:新的连接
*/
err_t   netconn_accept(struct netconn *conn, struct netconn **new_conn)

/*
接收数据
conn:连接
new_buf:数据包结构体
*/
err_t   netconn_recv(struct netconn *conn, struct netbuf **new_buf);
/*
tcp发送数据
conn:连接
dataptr:发送缓冲区
size:发送大小
apiflag:标志
*/
#define netconn_write(conn, dataptr, size, apiflags) \
          netconn_write_partly(conn, dataptr, size, apiflags, NULL)
/*
关闭tcp连接
conn:连接
*/
err_t   netconn_close(struct netconn *conn);

/*
udp发送数据
conn:连接
buf:数据包结构体
*/
err_t   netconn_send(struct netconn *conn, struct netbuf *buf);

三、netconn示例:编写TCP服务器

#include "my_netconn.h"
#include "lwip/opt.h"
#include "usart.h"

#if LWIP_NETCONN
#include "lwip/sys.h"
#include "lwip/api.h"

#define TCPECHO_THREAD_PRIO  (osPriorityAboveNormal)

static void mytcp_thread(void *arg)
{
   struct netconn *conn, *newconn;
   err_t err;
   
   u8_t  tx_buf[20];//发送缓冲区
   u16_t rx_len=0;
   u8_t *temp = "cnt:%d\r\n";
   u16_t cnt =0;//要通过TCP显示的计数值
  
   LWIP_UNUSED_ARG(arg);

   /* Create a new connection identifier. */
   /* Bind connection to well known port number 7. */
   conn = netconn_new(NETCONN_TCP);
   netconn_bind(conn, IP_ADDR_ANY, 7);

   LWIP_ERROR("my tcpdemo: invalid conn", (conn != NULL), return;);

   /* Tell connection to go into listening mode. */
   netconn_listen(conn);
   /* Grab new connection. */
   err = netconn_accept(conn, &newconn);
   printf("accepted new connection %p\n", newconn);
   /* Process the new connection. */
   if (err == ERR_OK) 
   {
     while (1) 
     {
	  sprintf(tx_buf,temp,cnt);
	  tx_len = strlen((const char *)tx_buf);
	  cnt++;
	  err = netconn_write(newconn, tx_buf, tx_len, NETCONN_COPY);
	  vTaskDelay(1000);
     }
   }
}
//创建tcp线程
void mytcp_init(void)
{
  sys_thread_new("tcpecho_thread", mytcp_thread, NULL, (configMINIMAL_STACK_SIZE*2), TCPECHO_THREAD_PRIO);
}
#endif /* LWIP_NETCONN */

四、测试

在这里插入图片描述

五、总结

使用netconn api首先使用netconn_new创建一个连接,接着可以对这个连接进行删除、查询ip和端口、绑定ip和端口、连接远端地址、监听、接收连接、接收数据、发送数据、关闭连接。非常简单的实现了TCP服务器。

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: lwip是一个轻量级网络协议栈,其中的netconn_listen函数用于将指定的TCP连接设置为监听模式。当lwip中的netconn_listen函数卡死时,可能由以下原因引起: 1.服务器资源不足:如果服务器处理的连接数超过其承载能力,就有可能导致netconn_listen函数卡死。这可能是由于服务器性能较低、负载过高或者并发连接数过多引起的。解决办法是优化服务器性能、增加服务器资源或者限制并发连接数。 2.网络丢包或拥塞:如果在netconn_listen函数执行期间发生网络丢包或者网络拥塞,可能会导致函数卡死。这可能是由于网络延迟、带宽限制或者网络故障引起的。解决办法是检查网络连接,保证网络质量良好,并且合理处理网络拥塞。 3.代码逻辑错误:netconn_listen函数在调用时的参数设置不正确,也有可能导致函数卡死。可以通过检查代码逻辑,确保正确使用该函数和传递正确的参数来解决该问题。 4.其他原因:除上述原因外,还有可能是由于硬件故障、软件冲突或者系统错误等引起的。可以通过重新启动硬件、解决软件冲突或者检查系统错误日志来解决这些问题。 在调试lwip中的netconn_listen函数卡死问题时,可以先排除以上可能原因,逐一检查并排查问题所在,以便找到合适的解决办法。 ### 回答2: lwip是一个用于嵌入式系统的网络协议栈,其中的netconn_listen函数用于将一个TCP连接的套接字设置为监听状态。然而,有时候netconn_listen函数可能会出现卡死的情况。 造成lwip netconn_listen卡死的原因有很多,以下是常见的一些可能原因: 1. 资源耗尽:如果系统中的资源不足,例如内存或者网络连接数达到了上限,netconn_listen函数可能会卡死。这通常发生在系统运行时间较长或者负载较高的情况下。 2. 配置问题:配置参数和系统设置的不正确或者不匹配也可能导致netconn_listen函数卡死。在使用lwip时,需要确保正确配置了网络设备和协议栈相关的参数,以及正确实现了必要的回调函数。 3. 网络问题:netconn_listen函数卡死还可能是由于网络相关问题造成的,例如网络连接不稳定、网络延迟过高等。 要解决lwip netconn_listen卡死的问题,可以尝试以下步骤: 1. 检查系统资源:确认系统的内存和网络连接数是否足够,如果不足,尝试增加资源。可以使用相关的性能分析工具来监视系统资源的使用情况。 2. 检查配置参数:仔细检查lwip的配置参数和设备驱动的配置,确保其正确性和一致性。 3. 进行网络调试:使用网络调试工具来分析网络连接的状态和性能,检查是否有网络相关的问题。 4. 更新lwip库版本:如果使用lwip库版本较旧,尝试更新到最新版本,以获取改进的稳定性和bug修复。 5. 检查应用程序代码:检查应用程序中关于lwip使用是否正确,确保正确调用netconn_listen函数,并且正确处理事件回调函数。 总之,要解决lwip netconn_listen卡死的问题,需要检查系统资源、配置参数、网络及应用程序代码,并根据问题的具体原因进行相应的调整和优化。 ### 回答3: lwip是一个轻量级的网络协议栈,netconn_listen是lwip中用于监听网络连接的函数。当调用netconn_listen函数时出现卡死的情况可能有以下几个原因: 1. 网络连接错误:可能是由于网络连接的问题,例如网络延迟或断开,导致调用netconn_listen函数时无法建立正确的连接,从而导致卡死。 2. 资源耗尽:如果系统资源(如内存)不足,或者已经达到了系统所能处理的最大连接数,调用netconn_listen函数可能会导致卡死。 3. 死锁:在多线程环境下,如果存在死锁情况,即多个线程相互等待对方释放的资源,调用netconn_listen函数可能会导致卡死。 为了解决这个问题,可以尝试以下几个方法: 1. 检查网络连接:确认网络连接是否正常,在执行netconn_listen函数之前,可以先检查网络状态,确保网络连接正常。 2. 调整系统资源:如果系统资源不足导致卡死,可以尝试增加系统可用资源,例如增加内存容量或调整系统的最大连接数。 3. 检查死锁情况:如果存在死锁情况,需要仔细检查代码逻辑,避免出现多个线程相互等待对方释放资源的情况,可以使用调试工具来定位并解决死锁问题。 总之,lwip netconn_listen卡死可能是由于网络连接错误、资源耗尽或死锁等原因引起的。需要通过排查问题所在,并采取相应的解决方案来解决这个问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值