STM32使用LWIP库新建tcp_sever

STM32使用LWIP库新建tcp_sever欢迎查看本文所在的系列 STM32 的 LWIP 应用 点击跳转 main 函数区域 1 是 lwip 的初始化 voidLwIP Init void structip addripaddr structip addrnetmask structip addrgw mem init 内存堆初始化 memp init 内存池初始化 IP4 ADDR

欢迎查看本文所在的系列,STM32的LWIP应用,点击跳转

main函数

STM32使用LWIP库新建tcp_sever

区域1是lwip的初始化
void LwIP_Init(void) { struct ip_addr ipaddr; struct ip_addr netmask; struct ip_addr gw; mem_init();//内存堆初始化 memp_init();//内存池初始化 IP4_ADDR(&ipaddr, 192, 168, 16, 211); IP4_ADDR(&netmask, 255, 255 , 255, 0); IP4_ADDR(&gw, 192, 168, 16, 1); netif_add(&netif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, ðernet_input);//添加新网卡到网卡列表 netif_set_default(&netif);//将网卡设置为默认网卡 netif_set_up(&netif);//打开网卡 }
区域2
void tcp_server_init(void) { /* create new tcp pcb */ tcp_server_pcb = tcp_new();//建立一个新的连接标志(pcb),在定义一个tcp_pcb控制块后应该首先被调用,以建立该控制块的连接标志 if (tcp_server_pcb != NULL) { err_t err; /* bind echo_pcb to port 7 (ECHO protocol) */ err = tcp_bind(tcp_server_pcb, IP_ADDR_ANY, 7);//绑定本地的IP地址和端口号,可以将其绑定在一个任意的本地IP地址上,它也只能在函数tcp_new()调用之后才能调用 if (err == ERR_OK) { /* start tcp listening for echo_pcb */ tcp_server_pcb = tcp_listen(tcp_server_pcb);//在绑定成功后,监听端口,在这里监听端口,说明是建立的服务器,与之对应的是tcp_connect,代表的是客户机 /* initialize LwIP tcp_accept callback function */ tcp_accept(tcp_server_pcb, tcp_server_accept);//接收后调用此函数 ,回调函数,通知LwIP一个新来的连接已经被接收,这其中tcp_server_accept是函数名字,这或许也应该叫回调函数的注册 printf("Create TCP server success"); printf("\r\nTCP server IP : 192.168.16.211"); printf("\r\nTCP server port: 7"); printf("\r\n\r\n"); } else { printf("Can not bind pcb\n"); } } else { printf("Can not create new pcb\n"); } }
下面讲解tcp_server_accept函数
static err_t tcp_server_accept(void *arg, struct tcp_pcb *newpcb, err_t err) { err_t ret_err; /* set priority for the newly accepted tcp connection newpcb */ tcp_setprio(newpcb, TCP_PRIO_MIN);//设置这个网络控制块的优先级 /* pass newly allocated es structure as argument to newpcb */ tcp_arg(newpcb, NULL);//传递一个参数 arg 给后面的调用使用,可以传一个结构体,指定应该传递给所有回调函数的应用程序的具体状态,详见下面的备注 /* initialize lwip tcp_recv callback function for newpcb */ tcp_recv(newpcb, tcp_server_recv);//当服务器接收到数据时调用tcp_server_recv函数 /* initialize lwip tcp_err callback function for newpcb */ tcp_err(newpcb, tcp_server_error);//当服务器出现错误时调用tcp_server_error函数 /* initialize lwip tcp_poll callback function for newpcb */ tcp_poll(newpcb, tcp_server_poll, 10);//定时调用tcp_server_poll函数,参数10,代表每间隔5s调用,其它看上面区域3的解释 /* initialize lwip tcp_sever_sent_ok callback function for newpcb */ tcp_sent(newpcb, tcp_sever_sent_ok);//当服务器发送完数据之后调用tcp_sever_sent_ok函数 ret_err = ERR_OK; return ret_err; }
备注:
关于 tcp_arg(newpcb, NULL);
我们传入的参数是NULL,为空
但是这个可以不传入空参数,详见官方demo

其中,我们看tcpsever接收函数
/ * @brief This function is the implementation for tcp_recv LwIP callback * @param arg: pointer on a argument for the tcp_pcb connection * @param tpcb: pointer on the tcp_pcb connection * @param pbuf: pointer on the received pbuf * @param err: error information regarding the reveived pbuf * @retval err_t: error code */ static err_t tcp_server_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { uint8 *p_data; uint32 data_len; if ((err == ERR_OK) && (p != NULL)){ tcp_server_send_back(tpcb, p); printf("TCP server returns the received data\r\n\r\n"); pbuf_free(p); }else{ if(tpcb->state == CLOSE_WAIT) { printf("TCP client downline\r\n"); printf("TCP client IP : %d.%d.%d.%d\r\n",(uint8)(tpcb->remote_ip.addr), (uint8)((tpcb->remote_ip.addr)>>8), (uint8)((tpcb->remote_ip.addr)>>16), (uint8)((tpcb->remote_ip.addr)>>24)); printf("TCP client port: %d",tpcb->remote_port); printf("\r\n\r\n"); tcp_arg(tpcb, NULL); tcp_sent(tpcb, NULL); tcp_recv(tpcb, NULL); tcp_err(tpcb, NULL); tcp_poll(tpcb, NULL, 0); /* close tcp connection */ tcp_close(tpcb); } } return ERR_OK; }

区域3:

整个lwip协议栈的定时调用功能,这个在本工程中使用的是在主循环中,在大工程中可以放在定时器中,

如果看文字版太枯燥,可以点击看视频版:点击跳转

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/232133.html原文链接:https://javaforall.net

(0)
上一篇 2025年10月30日 下午6:01
下一篇 2025年10月30日 下午6:22


相关推荐

  • lnk2019无法解析的外部符号_declspec_无法解析的外部符号lnk2001

    lnk2019无法解析的外部符号_declspec_无法解析的外部符号lnk2001VisualStudio2015编译中出现此问题:errorLNK2019:无法解析的外部符号__vsnprintf,该符号在函数xxxx中被引用解决方案:1、可能是由于某些头文件的函数或者未连接某些链接库所引起,故将头文件和链接库包含进去就OK。2、在项目工程属性中将MFC的使用变为“在共享DLL中使用MFC”3、编译时加入以下代码#include<Windows.h…

    2026年3月12日
    5
  • BZOJ4567 [SCOI2016]背单词

    BZOJ4567 [SCOI2016]背单词AddressBZOJ4567洛谷P3294Solution简化下题目,对于排在第xxx个位置的串:1.若存在该串的后缀排在该串后面,该串的代价为n2n2n^2。2.若该串没有后缀,代价为xxx。3.若该串的所有后缀都排在该串前面,记最靠近该串的后缀位置为yyy,代价为x−yx−yx-y。显然只要把所有串翻转,则后缀都变成了前缀,建出Trie…

    2022年7月26日
    13
  • python安装pygame教程_pygame 安装教程

    python安装pygame教程_pygame 安装教程步骤 1 去官网下载 PyGame 注意 要下载对应版本的包其中 如果 python 为以下版本 cp36 就是 python3 6 的意思 2 exe 文件直接安装 whl 文件启动 doc 命令安装 在文件所在位置打开 doc 界面 win10 直接在当前文件夹空白处按住 shift 右键打开 powershell 窗口 输入以下指令安装 pipinstallpy 1 9 3 cp36 cp36m

    2026年3月19日
    2
  • 清华持股超17亿元!清华孵化的科技成果转化公司估值达400亿

    清华持股超17亿元!清华孵化的科技成果转化公司估值达400亿

    2026年3月12日
    3
  • Java之基于注解的Excel导出

    Java之基于注解的Excel导出数据库 Excel 导出操作代码过于冗长惨不忍睹 无法复用 目录第一步 自定义注解 第二步 实体类 第三步 解析工具类 第四步 使用 注解配合工具类做了个小工具如下 第一步 自定义注解 packagecom ruoyi framework aspectj lang annotation importjava lang annotation Element

    2026年3月19日
    2
  • getmethod方法什么意思_getstring方法

    getmethod方法什么意思_getstring方法getMethod方法要注意的地方:类对象.getMethod(mName,HttpServletRequest.class,HttpServletResponse.class);第一个参数是mName“方法名称”第二个参数是“方法参数的类对象”//这个就是为什么他是.class的原因,为什么参数是类对象?因为这个是Java规定的举个例子  这是一个抽取出的通用的servlet(页面请求经过的第…

    2025年11月24日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号