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


相关推荐

  • 列车调度问题[通俗易懂]

    列车调度问题[通俗易懂]题目:高铁货运站的调配问题我们国家大力发展道路交通基础设施,最近这些年修建了大量的高铁线路,以促进国内的物资运输和调配,ZZ是一个超级货运站,是连接亚欧货运的枢纽站,现在ZZ货运站列车调度铁轨的结构如下图所示。两端分别是一条入口(Entrance)轨道和一条出口(Exit)轨道,它们之间有N条平行的轨道。每趟列车从入口可以选择任意…

    2022年7月26日
    8
  • loadrunner11中文版激活成功教程文档+录制脚本(图/文)「建议收藏」

    loadrunner11中文版激活成功教程文档+录制脚本(图/文)「建议收藏」LoadRunner11安装1.Loadrunner11下载链接:https://pan.baidu.com/s/15Svt3ktg2Tq5QVslpQcXKA密码:mtxh   2.点击安装文件中的【setup】打开安装文件中,本次安装【LoadRunner完整安装程序】,若需要仅安装LoadGenerator等则根据实际需要进行选择。点击后会弹出重启电脑的提示信息。建议点击【是(Y)】之后…

    2022年7月22日
    15
  • linux如何查看进程_java读取一个文件夹下的所有文件

    linux如何查看进程_java读取一个文件夹下的所有文件linux查看java进程路径_Linux查看java进程执行文件所在目录/具体位置(多文件夹同名jar包),重命名包,删除包

    2022年8月23日
    15
  • MybatisCodeHelperNew-2.9.3-183-204激活码-激活码分享

    (MybatisCodeHelperNew-2.9.3-183-204激活码)JetBrains旗下有多款编译器工具(如:IntelliJ、WebStorm、PyCharm等)在各编程领域几乎都占据了垄断地位。建立在开源IntelliJ平台之上,过去15年以来,JetBrains一直在不断发展和完善这个平台。这个平台可以针对您的开发工作流进行微调并且能够提供…

    2022年3月30日
    152
  • 分类模型的f1值大概是多少_准确率召回率f1分数

    分类模型的f1值大概是多少_准确率召回率f1分数欢迎您对PaddleHub提出建议,非常感谢您对PaddleHub的贡献!目前PaddleHub已实现您提出的需求,请安装PaddleHub>=1.7.0,PaddlePaddle>=1.8.0快速体验。请您在定义task任务时增加metrics_choices=[‘f1’]选项,即可实现多分类F1Score评估指标,示例如下:task=hub.ImageClassifierT…

    2022年10月14日
    2
  • vue父子组件传值 简单了解vuex

    vue父子组件传值 简单了解vuex一、vue的父子组件之间是如何传值的?首先呢,需要说说的是,vue既然有双向绑定,那为何会有父子组件之间的传值问题?这个问题也简单,vue的组件会供其他的vue页面进行调用,如果数组都是双向绑定的话,那么就容易混乱了,比如a,b页面绑了一个num=10,那b,c页面又绑了num=5,那vue实例的num到底听谁的?所以,这就是vue官网为什么说组件之间的数据只能是单项流通的,而且由父组件传递给…

    2022年5月16日
    95

发表回复

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

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