当前位置: 首页 > news >正文

4.物联网LWIP之C/S编程,stm32作为服务器,stm32作为客户端,代码的优化

LWIP配置

服务器端实现

客户端实现

错误分析

一。LWIP配置(FREERTOS配置,ETH配置,LWIP配置)

1.FREERTOS配置

 为什么要修改定时源为Tim1?不用systick?

原因:HAL库与FREERTOS都需要使用systick,两者冲突,所以修改时钟源,让FREERTOS使用Tim1。

 2.ETH配置

 3.LWIP配置

不使用DHCP

 4.步骤:
(1)freertos.c中会自己出现一个Lwip初始化

运行后结果:命令行中输入ping 192.168.1.10有回复

 二。服务器端

实验一:《stm32作为服务器端,COMMBOX串口作为客户端》

1.功能分析

小写转大写

 2.步骤:

(1)建立socket_tcp_server.h

#ifndef SOCKET_TCP_SERVER_H
#define SOCKET_TCP_SERVER_H#define SERVER_IP				"192.168.1.11"
#define SERVER_PORT			6666
#define BUFF_SIZE				1024void vTcpServerTask(void);#endif

 (2)建立socket_tcp_server.c,并添加到文件中

#include "socket_tcp_server.h"
#include "lwip/sockets.h"
#include "ctype.h"char ReadBuff[BUFF_SIZE];/*** @brief  TCP 服务器任务* @param  None* @retval None*/
void vTcpServerTask(void){int 	 sfd, cfd, n, i;struct sockaddr_in server_addr, client_addr;socklen_t	client_addr_len;//创建socketsfd = socket(AF_INET, SOCK_STREAM, 0);server_addr.sin_family 			= AF_INET;server_addr.sin_port   			= htons(SERVER_PORT);server_addr.sin_addr.s_addr = htonl(INADDR_ANY);//绑定socketbind(sfd, (struct sockaddr *)&server_addr, sizeof(server_addr));//监听socketlisten(sfd, 5);//等待客户端连接client_addr_len = sizeof(client_addr);cfd = accept(sfd, (struct sockaddr *)&client_addr, &client_addr_len);printf("client is connect cfd = %d\r\n",cfd);while(1){//等待客户端发送数据n = read(cfd, ReadBuff, BUFF_SIZE);//进行大小写转换for(i = 0; i < n; i++){ReadBuff[i] = toupper(ReadBuff[i]);		}//写回客户端write(cfd, ReadBuff, n);}
}

(3)freertos.c中网络任务中,添加服务器运行函数。

 不要忘记添加头文件

	vTcpServerTask();	

3.现象演示

(1)使用COMMBOX串口调试工程,添加socket网络客户端 ,目标ip为stm32的ip.端口在.h中

(2)stm32客户端发送的字母变大写

 三。客户端创建

实验二:《stm32作为客户端,COMMBOX串口作为服务器端》

1.创建socket_tcp_client.c与socket_tcp_client.h

(1)socket_tcp_client.c

#include "socket_tcp_server.h"
#include "socket_tcp_client.h"
#include "lwip/sockets.h"
#include "ctype.h"static char ReadBuff[BUFF_SIZE];void vTcpClientTask(void)
{int 	 cfd, n, i;struct sockaddr_in server_addr;//创建socketcfd = socket(AF_INET, SOCK_STREAM, 0);server_addr.sin_family 			= AF_INET;server_addr.sin_port   			= htons(SERVER_PORT);server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);//连接到服务器connect(cfd, (struct sockaddr*)&server_addr, sizeof(server_addr));printf("server is connect ok\r\n");while(1){//等待服务器发送数据n = read(cfd, ReadBuff, BUFF_SIZE);//进行大小写转换for(i = 0; i < n; i++){ReadBuff[i] = toupper(ReadBuff[i]);		}//写回服务器write(cfd, ReadBuff, n);}
}

(2)socket_tcp_client.h

#ifndef _SOCKET_TCP_CLIENT_H
#define _SOCKET_TCP_CLIENT_Hvoid vTcpClientTask(void);#endif

可能遇到的问题:

        由于打开了防火墙,所以无法连接

 

 补充:上述代码的问题

        1.代码封装性不好

        2.代码对边界错误提示太少

四。代码的优化

1.函数在封装,文件为socket_warp.c与socket_warp.h

(1)socket_warp.h

#ifndef _SOCKET_WRAP_H
#define _SOCKET_WRAP_H#include "lwip/sockets.h"int Socket(int domain, int type, int protocol);int Bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);int Listen(int sockfd, int backlog);int Accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
int Connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);int Write(int fd,const void *buf,size_t nbytes);
int Read(int fd,void *buf,size_t nbyte);int Sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
int Recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, socklen_t *fromlen);#endif

(2)socket_warp.c

#include "socket_wrap.h"
#include "FreeRTOS.h"
#include "task.h"int Socket(int domain, int type, int protocol){int fd;fd=socket(domain,type,protocol);if(fd<0){printf("create socket error\n");//没有创建完成,那么这个任务也没有必要运行,直接切换上下文//返回一个小于零的数vTaskDelete(NULL);}return fd;
}int Bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen){int ret;ret=bind(sockfd,addr,addrlen);if(ret < 0){printf("bind socket error\r\n");//当调用删除任务,就会切换上下文,CPU执行其他任务vTaskDelete(NULL);		}return ret;
}int Listen(int sockfd, int backlog){int ret;ret=listen(sockfd,backlog);if(ret<0){printf("listen socket error\n");vTaskDelete(NULL);}return ret;
}int Accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen){int fd;
again:	fd=accept(sockfd,addr,addrlen);if(fd<0){printf("accept socket error\n");goto again;}return fd;
}
int Connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen){int ret;ret=connect(sockfd,addr,addrlen);if(ret<0){printf("connect socket error\n");//先关闭当前的socket,其实内部是删除这个socket的内存块,不删除会导致下次无法生成close(sockfd);}return ret;
}int Write(int fd,const void *buf,size_t nbytes){int ret;ret=write(fd,buf,nbytes);//没有书写完成就关闭socketif(ret<0){printf("write socket error\n");close(fd);}return ret;
}
int Read(int fd,void *buf,size_t nbyte){int ret;ret=read(fd,buf,nbyte);if(ret==0){printf("read socket is close\n");close(fd);}else if(ret<0){printf("read socket error\n");close(fd);}
}int Sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen){int ret;
again:	ret=sendto(sockfd,msg,len,flags,to,tolen);if(ret<0){printf("sendto socket error\n");goto again;}return ret;
}int Recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, socklen_t *fromlen){int ret;
again:	ret=recvfrom(sockfd,buf,len,flags,from,fromlen);if(ret<0){printf("recvfrom socket error\n");goto again;				}return ret;
}

上述为封装函数,包括tcp_server,tcp_client已经后续的udp_server

2.socket_tcp_server.c与socket_tcp_client.c

1.socket_tcp_server.c

#include "socket_udp_server.h"
#include "socket_tcp_server.h"
#include "socket_wrap.h"
#include "ctype.h"static char ReadBuff[BUFF_SIZE];void vUdpServerTask(){int 	 sfd, n, i;struct sockaddr_in server_addr, client_addr;socklen_t	client_addr_len;int optval=1;//创建socketsfd=Socket(AF_INET, SOCK_DGRAM, 0);setsockopt(sfd,SOL_SOCKET ,SO_BROADCAST,&optval,sizeof(optval));//绑定socketserver_addr.sin_family 			= AF_INET;server_addr.sin_port   			= htons(SERVER_PORT);server_addr.sin_addr.s_addr = htonl(INADDR_ANY);Bind(sfd, (struct sockaddr *)&server_addr, sizeof(server_addr));//处理client_addr_len=sizeof(client_addr);while(1){//等待客户端发送数据n = Recvfrom(sfd, ReadBuff, BUFF_SIZE, 0, (struct sockaddr *)&client_addr, &client_addr_len);ReadBuff[n] = '\0';printf("recv data:%s\r\n",ReadBuff);//进行大小写转换for(i = 0; i < n; i++){	ReadBuff[i] = toupper(ReadBuff[i]);		}//写回客户端Sendto(sfd, ReadBuff, n, 0, (struct sockaddr *)&client_addr, client_addr_len);}}

2.socket_tcp_client.c

#include "socket_tcp_server.h"
#include "socket_tcp_client.h"
#include "socket_wrap.h"
#include "ctype.h"
#include "FreeRTOS.h"
#include "task.h"#include "string.h"static char ReadBuff[BUFF_SIZE];void vTcpClientTask(void)
{int 	 cfd, n, i, ret;struct sockaddr_in server_addr;//	int so_reuseaddr_val = 1;
again://创建socketcfd = Socket(AF_UNSPEC, SOCK_STREAM, 0);//使能socket层 心跳检测
//	setsockopt(cfd, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr_val, sizeof(int));server_addr.sin_family 			= AF_INET;server_addr.sin_port   			= htons(SERVER_PORT);server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);	//连接到服务器//connect 其实是一个阻塞接口,内部要完成TCP的三次握手,当然有超时机制,所以我们需要等一段时间,才能重新连接到服务器ret = connect(cfd, (struct sockaddr*)&server_addr, sizeof(server_addr));if(ret < 0){//100ms去连接一次服务器vTaskDelay(1000);printf("connect fail\r\n");goto again;}printf("server is connect ok\r\n");while(1){//等待服务器发送数据n = Read(cfd, ReadBuff, BUFF_SIZE);if(n <= 0){goto again;}//进行大小写转换for(i = 0; i < n; i++){ReadBuff[i] = toupper(ReadBuff[i]);		}//写回服务器n = Write(cfd, ReadBuff, n);if(n <= 0){goto again;}}
}

结果:pc端的COMMBOX创建或者关闭服务器或者客户端时,串口都会打印出内容,提示打开或者关闭。

相关文章:

4.物联网LWIP之C/S编程,stm32作为服务器,stm32作为客户端,代码的优化

LWIP配置 服务器端实现 客户端实现 错误分析 一。LWIP配置&#xff08;FREERTOS配置&#xff0c;ETH配置&#xff0c;LWIP配置&#xff09; 1.FREERTOS配置 为什么要修改定时源为Tim1&#xff1f;不用systick&#xff1f; 原因&#xff1a;HAL库与FREERTOS都需要使用systi…...

【C语言】扫雷游戏(可展开)——超细教学

&#x1f6a9;纸上得来终觉浅&#xff0c; 绝知此事要躬行。 &#x1f31f;主页&#xff1a;June-Frost &#x1f680;专栏&#xff1a;C语言 &#x1f525;该篇将运用数组来实现 扫雷游戏。 目录&#xff1a; &#x1f31f;思路框架测试游戏 &#x1f31f;测试部分函数实现&am…...

数据的深海潜行:数据湖、数据仓库与数据湖库之间的微妙关系

导言&#xff1a;数据的重要性与存储挑战 在这个信息爆炸的时代&#xff0c;数据已经成为企业的核心资产&#xff0c;而如何高效、安全、便捷地存储这些数据&#xff0c;更是每个组织面临的重大挑战。 数据作为组织的核心资产 数据在过去的几十年里从一个辅助工具演变成企业的…...

Docker 安装 Redis集群

1. 面试题 1.1 1~2亿条数据需要缓存&#xff0c;请问如何设计这个存储案例 单机单台不可能实现&#xff0c;肯定是用分布式存储&#xff0c;用redis如何落地&#xff1f; 1.2 上述问题工程案例场景设计类题目&#xff0c;解决方案 1.2.1 哈希取余分区 2亿条记录就是2亿个k,v&…...

数据结构入门 — 链表详解_单链表

前言 数据结构入门 — 单链表详解* 博客主页链接&#xff1a;https://blog.csdn.net/m0_74014525 关注博主&#xff0c;后期持续更新系列文章 文章末尾有源码 *****感谢观看&#xff0c;希望对你有所帮助***** 系列文章 第一篇&#xff1a;数据结构入门 — 链表详解_单链表 第…...

从零学算法151

151.给你一个字符串 s &#xff0c;请你反转字符串中 单词 的顺序。 单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。 返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。 注意&#xff1a;输入字符串 s中可能会存在前导空格、尾随…...

【Vue】动态设置元素类以及样式

Vue2 动态设置元素类以及样式 1.动态设置类 class 1.1 字符串语法 通过v-bind绑定元素的class属性&#xff0c;为其指定一个字符串&#xff1a; <div v-bind:class"className">class动态绑定</div> <script> export default {data() {return {…...

node和前端项目宝塔部署

首先需要一台服务器 购买渠道&#xff1a;阿里云、腾讯云、百度云、华为云 一、以阿里云为例 购买esc 可临时购买测试服务器 二、安装宝塔 复制公网ip地址 通过Xshell 进行账号密码的连接 连接后访问宝塔官网 宝塔面板下载&#xff0c;免费全能的服务器运维软件 找到自己…...

【Python原创毕设|课设】基于Python Flask的上海美食信息与可视化宣传网站项目-文末附下载方式以及往届优秀论文,原创项目其他均为抄袭

基于Python Flask的上海美食信息与可视化宣传网站&#xff08;获取方式访问文末官网&#xff09; 一、项目简介二、开发环境三、项目技术四、功能结构五、运行截图六、功能实现七、数据库设计八、源码获取 一、项目简介 随着大数据和人工智能技术的迅速发展&#xff0c;我们设…...

【HTML】HTML面试知识梳理

目录 DOCTYPE&#xff08;文章类型&#xff09;head标签浏览器乱码的原因及解决常用的meta标签与SEOscript标签中defer和async的区别src&href区别HTML5有哪些更新语义化标签媒体标签表单进度条、度量器DOM查询Web存储Canvas和SVG拖放 &#xff08;HTML5 drag API&#xff0…...

Java进阶篇--IO流的第二篇《多样的流》

目录 Java缓冲流 BufferedReader和BufferedWriter类 Java随机流 Java数组流 字节数组流 ByteArrayInputStream流的构造方法&#xff1a; ByteArrayOutputStream流的构造方法&#xff1a; 字符数组流 Java数据流 Java对象流 Java序列化与对象克隆 扩展小知识&#x…...

iPhone 14 Pro 动态岛的功能和使用方法详解

当iPhone 14 Pro机型发布时,苹果公司将软件功能与屏幕顶部的药丸状切口创新集成,称之为“灵动岛”,这让许多人感到惊讶。这篇文章解释了它的功能、工作原理,以及你如何与它互动以执行动作。 一、什么是灵动岛?它是如何工作的 在谣言周期的早期‌iPhone 14 Pro‌ 在宣布时…...

掌握这20条你将超过90%的测试员

1、不断学习 不管是“软技能”&#xff0c;比如公开演讲&#xff0c; 或者编程语言&#xff0c;亦或新的测试技术&#xff0c;成功的软件测试工程师总是会从繁忙中抽出时间来坚持学习。 2、管理你的时间 我们的时间很容易被大块的工作和不断的会议所占据&#xff0c;导致我们…...

LightDB create table时列约束支持enable/disable关键字

功能介绍 为了方便用户从Oracle数据库迁移到LightDB数据库&#xff0c;LightDB从23.3版本开始支持 create table时列约束支持enable/disable关键字。这个功能仅是语法糖。 使用说明 执行create table时&#xff0c;列约束后面可以选择性添加enable/disable关键字。 create …...

使用BeeWare实现iOS调用Python

1、准备工作 1.1、安装Python 1.2、设置虚拟环境 我们现在将创建一个虚拟环境——一个“沙盒”&#xff0c;如果我们将软件包安装到虚拟环境中&#xff0c;我们计算机上的任何其他Python项目将不会受到影响。如果我们把虚拟环境搞得一团糟&#xff0c;我们将能够简单地删除它…...

无公网IP内网穿透使用vscode配置SSH远程ubuntu随时随地开发写代码

文章目录 前言1、安装OpenSSH2、vscode配置ssh3. 局域网测试连接远程服务器4. 公网远程连接4.1 ubuntu安装cpolar内网穿透4.2 创建隧道映射4.3 测试公网远程连接 5. 配置固定TCP端口地址5.1 保留一个固定TCP端口地址5.2 配置固定TCP端口地址5.3 测试固定公网地址远程 前言 远程…...

二叉树、红黑树、B树、B+树

二叉树 一棵二叉树是结点的一个有限集合&#xff0c;该集合或者为空&#xff0c;或者是由一个根节点加上两棵别称为左子树和右子树的二叉树组成。 二叉树的特点&#xff1a; 每个结点最多有两棵子树&#xff0c;即二叉树不存在度大于2的结点。二叉树的子树有左右之分&#xf…...

12,【设计模式】工厂

设计模式工厂 通过工程来构建任意参数对象&&std::forwardstd::move 在C中&#xff0c;“工厂”&#xff08;Factory&#xff09;是一种设计模式&#xff0c;它提供了一种创建对象的方式&#xff0c;将对象的创建和使用代码分离开来&#xff0c;提高了代码的可扩展性和可…...

mysql 8.0 窗口函数 之 分布函数 与 sql server (2017以后支持) 分布函数 一样

mysql 分布函数 percent_rank&#xff08;&#xff09; &#xff1a;等级值 百分比cume_dist() &#xff1a;累积分布值 percent_rank&#xff08;&#xff09; 计算方式 (rank-1)/(rows-1)&#xff0c; 其中 rank 的值为使用RANK()函数产生的序号&#xff0c;rows 的值为当前…...

Python Opencv实践 - 图像直方图自适应均衡化

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/cat.jpg", cv.IMREAD_GRAYSCALE) print(img.shape)#整幅图像做普通的直方图均衡化 img_hist_equalized cv.equalizeHist(img)#图像直方图自适应均衡化 #1. 创…...

Linux编程:在程序中异步的调用其他程序

Linux编程:execv在程序中同步调用其他程序_风静如云的博客-CSDN博客 介绍了同步的调用其他程序的方法。 有的时候我们需要异步的调用其他程序,也就是不用等待其他程序的执行结果,尤其是如果其他程序是作为守护进程运行的,也无法等待其运行的结果。 //ssss程序 #include …...

04有监督算法——支持向量机

1.支持向量机 1.1 定义 支持向量机( Support Vector Machine &#xff09;要解决的问题 什么样的法策边界才是最好的呢? 特征数据本身如果就很难分,怎么办呢? 计算复杂度怎么样?能实际应用吗? 支持向量机&#xff08; Support Vector Machine , SVM)是一类按监督学习( s…...

macos 使用vscode 开发python 爬虫(安装一)

使用VS Code进行Python爬虫开发是一种常见的选择&#xff0c;下面是一些步骤和建议&#xff1a; 安装VS Code&#xff1a;首先&#xff0c;确保你已经在你的macOS上安装了VS Code。你可以从官方网站&#xff08;https://code.visualstudio.com/&#xff09;下载并安装最新版本…...

专有网络VPC私网/公网类产品选择

私网类产品选择 VPC互连&#xff1a;云企业网&#xff0c;对等连接 VPC与本地IDC互连&#xff1a;VPN网关&#xff0c;高速通道&#xff0c;云企业网&#xff0c;智能接入网关 VPC与多站点连接&#xff1a;VPN网关&#xff0c;智能接入网关&#xff0c;VPN网关高速通道 远程接…...

Connect-The-Dots靶场

靶场下载 https://www.vulnhub.com/entry/connect-the-dots-1,384/ 一、信息收集 探测存活主机 netdiscover -r 192.168.16.161/24nmap -sP 192.168.16.161/24端口操作系统扫描 nmap -sV -sC -A -p 1-65535 192.168.16.159扫描发现开放端口有 21 ftp 80 http 20…...

Linux解决RocketMQ中NameServer启动问题

启动步骤可以查看官网&#xff0c;https://github.com/apache/rocketmq 一下说明遇到的问题。 1&#xff1a;ROCKETMQ_HOME问题 根据官网提示进入mq/bin目录下&#xff0c;可以使用./mqnamesrv进行NameServer启动&#xff0c;但是会遇到第一个问题&#xff0c;首次下载Rocket…...

js逆向实战之某书protobuf反序列化

什么是Protobuf&#xff1f; \qquad Protobuf&#xff08;Protocol Buffer&#xff09;是 Google 开发的一套数据存储传输协议&#xff0c;作用就是将数据进行序列化后再传输&#xff0c;Protobuf 编码是二进制的&#xff0c;它不是可读的&#xff0c;也不容易手动修改&#xf…...

cpolar+JuiceSSH实现手机端远程连接Linux服务器

文章目录 1. Linux安装cpolar2. 创建公网SSH连接地址3. JuiceSSH公网远程连接4. 固定连接SSH公网地址5. SSH固定地址连接测试 处于内网的虚拟机如何被外网访问呢?如何手机就能访问虚拟机呢? cpolarJuiceSSH 实现手机端远程连接Linux虚拟机(内网穿透,手机端连接Linux虚拟机) …...

[MyBatis系列②]Dao层开发的两种方式

目录 1、传统开发 1.1、代码 1.2、存在的问题 2、代理开发 2.1、开发规范 2.2、代码 ⭐mybatis系列①&#xff1a;增删改查 1、传统开发 传统的mybatis开发中&#xff0c;是在数据访问层实现相应的接口&#xff0c;在实现类中用"命名空间.id"的形式找到对应的映…...

言语理解-中心理解之主题词及行文脉络

例题 例题 例题 例题 例题 例题...

广州英文网站建设/沈阳网站seo公司

0x1、Android Support Library的由来 Android 3.0 (API 11) 为了更好地兼容平板&#xff0c;加入了Fragment&#xff0c;而想让低版本的系统也能用上&#xff0c;需要做一个 向下兼容&#xff0c;于是Android团队推出了Android Support Library。 老Android们熟知的下述库 (v后…...

凡科网的网站建设怎么做/免费二级域名分发网站

1.Linux的启动过程 作为一台计算机&#xff0c;启动它的第一步是加电自检&#xff0c;也就是给电脑用电然后按电源按钮开机。加电之后的运行步骤:(1)加载bios&#xff0c;然后检查硬盘信息(2)读取MBR的配置(MBR就是硬盘第一个扇区第一个磁道的第一个磁头的位置)&#xff0c;去找…...

网页制作公司地址/班级优化大师的优点

从sqlite数据库导入到mysql数据库实例从sqllite中导出数据文件库XX.sql的文件。导入到mysql数据库中。键入命令&#xff1a; source /smb/works/mysql.sql出现很多如下的错误&#xff1a;You have an error in your SQL syntax; check the manual thatcorresponds to your Mari…...

wordpress英文版下载地址/六盘水seo

正确卸载CleanMyMac 想要卸载CleanMyMac比较好的方法就是通过它本身卸载。它的卸载功能可以帮助我们解决很多软件难卸载问题。 点击界面中的“卸载器”选项&#xff0c;勾选选框&#xff0c;点击“卸载”即可&#xff0c;操作非常简单且能准确清除应用程序所有的安装文件。 若…...

湖南手机网站建设公司/万网域名管理平台

...

wordpress 判断页面名称/宁波免费建站seo排名

原文:C#设计模式之三抽象工厂模式&#xff08;AbstractFactory&#xff09;【创建型】一、引言 写了3篇有关设计模式的文章了&#xff0c;大家有了些反馈&#xff0c;说能从中学到一些东西&#xff0c;我感到很欣慰&#xff0c;那就继续努力。今天我要写第四个模式了&#…...