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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 如何从Java官网下载 Java API 文档

    如何从Java官网下载 Java API 文档1 登录 Oracle 官网 https www oracle com 2 进入 Java 页面 3 将页面拉到底部 4 将页面拉到中间 5 6 7 将页面下拉 8 9 1011 下载完成后解压到任意目录 打开 doc api 目录 打开 index 页面 尽情享受即可

    2025年9月20日
    4
  • php数据库根据手机号获取归属地,PHP通过API获取手机号码归属地

    php数据库根据手机号获取归属地,PHP通过API获取手机号码归属地该API接口自2011年SAE平台上线稳定运行至今,增加了17号段的支持,欢迎各种采集注限制,并发10详细使用说明接口地址:http://appyun.sinaapp.com/index.php?app=mobile&controller=index&action=api请求方法:GET请求参数:参数名类型必填参数位置描述默认值appstring是urlPar…

    2022年7月22日
    13
  • python的三种取整方式_python取整函数-取整函数,PYTHON[通俗易懂]

    python的三种取整方式_python取整函数-取整函数,PYTHON[通俗易懂]本教程分享:《python取整函数》,python有什么办法使得int按照”四舍五入”的方式取…由于小数取整会采用比较暴力的截断方式,即向下取整,所以要想使得int()按照“四舍五入”的方式取整,可以采用如下方法:5.4“四舍五入”结果为:5,int(5.4+0.5)==55.6“四舍五入”结果为:6,int(5.6+0.5)==6python为什么算除法自动取整了。如图…

    2025年7月15日
    6
  • react路由权限设置

    react路由权限设置说明在react项目中有时我们的一些页面需要权限才能访问,这里以需要登录才能访问进行的设置在这里可以看到权限页面和关于页面是需要登录才能访问的importReact,{Component,useState,useEffect,useRef}from’react’;import{HashRouterasRouter,Route,NavLink,Redirect,Switch,useHistory}from”react-router-dom”;classAPP

    2022年5月6日
    177
  • C语言如何计算数组的长度

    C语言如何计算数组的长度(1)借助sizeof()函数:#include<stdio.h>intmain(){ //定义一个整型数组,并进行初始化赋值9个数据:  intarr[]={1,2,3,4,5,6,7,8,9}; intlength=0; //计算数组中数据长度: //所有数据的字节数除以一个数据的字节数即为数据的个数:  length=sizeof(arr)/…

    2022年7月27日
    6
  • 自然常数e的由来(简单通俗易于理解自然常数e)「建议收藏」

    自然常数e的由来(简单通俗易于理解自然常数e)「建议收藏」自然常数e的由来 (该文章用于自学和分享) 开篇先讲两个例子苏格拉底的麦穗柏拉图问苏格拉底,什么是爱情。苏格拉底说,这样吧,你去麦田里,不要回头,一直往前走,把你遇到的、最大的那棵麦穗摘下来、拿给我。后面的事,大家都知道了:柏拉图瞻前顾后,总觉得后面还有更好的,结果两手空空、一棵麦穗也没有得到。 除此之外,梅里尔·弗勒德(MerrillFlood)【提出过博弈论中…

    2025年7月21日
    4

发表回复

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

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