基于多协议传感器的桥梁监测数据采集与管理系统设计

news2024/11/26 19:42:01

文章目录

  • 前言
    • 1、要求:
    • 2、系统框图
      • 2.1系统总体框图
      • 2.2、stm32通过AHT20采集温湿度框图:
      • 2.3、stm32通过modbus协议与上位机通信框图:
    • 3、ModBus协议
      • 1、协议概述
      • 2、Modbus主/从协议原理
      • 3、通用Modbus帧结构---协议数据单元(PDU)
      • 4、两种Modbus串行传输模式
      • 5、ModbusTCP通信结构
      • 6、系统涉及到的通讯协议指令
      • 7、部分协议功能码
  • 一、MCU数据采集与上位机通信
    • 1、温湿度采集(I2C协议)
    • 2、上位机通信
  • 二、传感器仿真数据远程采集
    • 1.TCP套接字和modbus协议
    • 2.UDP套接字和modbus协议
  • 三、思考题
  • 四、总结


前言

1、要求:

1.MCU数据采集与上位机通信:
采用STM32F103开发板+AHT20 模拟多监测点的温湿度数据采集。用串口/485总线完成采集终端与上位机进行数据传输。上位机可以运行Linux系统的树莓派3B+ (树莓派具备串口和有线、无线网络)。如果没有树莓派实物,可用PC机模拟,采用标准C语言或者python编程实现。
2.传感器仿真数据远程采集:
研究内容包括:RS485总线与ModBus通讯协议、数据库技术、网络通信编程开发。
上位机通过UDP/TCP套接字和Modbus应用层协议,完成至少两类数据(比如温湿度、应力)的远程周期性(比如30秒)实时采集和保存。采集数据写入Mysql数据库,Mysql可以安装在本地PC机上Win10或Ubuntu系统上。一条采集数据记录至少包括:时间戳、采集点编号、采集数据类型、采集数据信息。软件开发采用编程软件不作限定。
3.思考:
针对实际工程应用中的多传感器、多协议、多组网方式的复杂多变的技术要求,如果采用FPGA开发板编程的灵活定制特点来设计实现不同各种接口协议,是否存在合理性?有什么优势和弊端? 请简要对比分析。

注意:主要是方案的设计与编程调试。

2、系统框图

2.1系统总体框图

在这里插入图片描述

2.2、stm32通过AHT20采集温湿度框图:

在这里插入图片描述

这个模块我们计划采用的是AHT20温湿度传感器,通过I2C与stm32进行通信,stm32再通过ModBus协议进行上传通信。

2.3、stm32通过modbus协议与上位机通信框图:

在这里插入图片描述

上位机则利用 Modbus 协议发送指令,并接受从机的数据,同时要求上位机将接收到的数据储存在数据库中,并能从给定的 dmo-monitor.igong.com 读取已经部署的桥梁传感器的数据。

3、ModBus协议

由上面的系统框图可以看出,我们对modbus协议使用较多,我们这里阐述一下modbus协议的内容。

1、协议概述

1、Modbus协议是一种串行通信协议,是Modicon公司(现在的施耐德电气Schneider Electric)于1979年为使用可编程逻辑控制器(PLC)通信而发表的。Modbus协议是应用层协议,已经成为工业领域通信协议的业界标准,是工业电子设备之间常用的连接方式。
2、Modbus是一个master/slave架构的协议,有一个节点是master节点,其他使用Modbus协议参与通信的节点是slave节点,每一个slave设备都有一个唯一的地址。只有被指定为master节点的节点可以启动一个命令。所有的Modbus数据帧包含了校验码,保证传输的正确性。基本的ModBus命令能指令一个slave设备改变它的寄存器的某个值,控制或者读取一个I/O端口,以及指挥设备回送一个或者多个其寄存器中的数据。

2、Modbus主/从协议原理

Modbus串行链路协议是一个主-从协议。在同一时间,只能将一个主站连接到总线,将一个或多个从站(最大数量为247)连接到相同的串行总线。Modbus 通讯总是由主站发起,当从站没有收到来自主站的请求时,将不会发送数据。主站同时只能启动一个Modbus事务处理,从站之间不能相互通信。

在这里插入图片描述

3、通用Modbus帧结构—协议数据单元(PDU)

Modbus协议定义了一个与基础通信层无关的简单协议数据单元(PDU),特定总线或网络上的Modbus协议映射能够在应用数据单元(ADU)上引入一些附加域。

在这里插入图片描述

4、两种Modbus串行传输模式

RTU模式:每个8 Bit字节包含两个4 Bit的十六进制字符,其优点是在同样的波特率下,可比ASCII方式传送更多的数据,但是每个信息必须以连续的数据流传输。

在这里插入图片描述

ASCII模式:信息中的每个8 Bit字节需2个ASCII字符,其优点是准许字符的传输间隔达到1s 而不产生错误;

在这里插入图片描述

5、ModbusTCP通信结构

Modbus TCP/IP的通信设备:连接至TCP/IP网络的 Modbus TCP/IP客户机和服务器设备。
互连设备如:在TCP/IP网络和串行链路子网之间互连的网桥、路由器或网关等设备。

在这里插入图片描述

6、系统涉及到的通讯协议指令

在这里插入图片描述

7、部分协议功能码

在这里插入图片描述

一、MCU数据采集与上位机通信

1、温湿度采集(I2C协议)

温湿度读取模块这里我们采用的传感器是AHT20、I2C协议。I2C 通讯协议(Inter-Integrated Circuit)是由 Phiilps 公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要 USART、CAN 等通讯协议的外部收发设备,现在被广泛地
使用在系统内多个集成电路(IC)间的通讯。

1、上电后等待一段时间待设备正常工作后再读取温湿度:

  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_USART1_UART_Init();
  uint32_t CT_data[2]={0,0};	
  volatile int  c1,t1;
  rt_thread_delay(50);
  AHT20_Init();
  rt_thread_delay(2500);

2、CRC校验后读取温湿度数据,随后延时5分钟


    AHT20_Read_CTdata_crc(CT_data);  //crc校验后,读取AHT20的温度和湿度数据 
	  c1 = CT_data[0]*100*10/1024/1024;  //计算得到湿度值c1(放大了10倍)
	  t1 = CT_data[1]*200*10/1024/1024-500;//计算得到温度值t1(放大了10倍)	
		printf("湿度:%d%s",c1/10,"%");
	  printf("温度:%d%s",t1/10,"℃");
	  printf("\r\n");
		rt_thread_mdelay(300000);//线程睡眠大约5分钟,挂起执行其他操作

2、上位机通信

这里我们的要求是模拟多监测点的温湿度数据的采集,这里我们可以采用移植RT-thread Nano的多任务处理框架,以防其他传感器的正常工作。

main函数中对Modbus 协议进行使能,并初始化 RT-Thread 进程:

eMBInit( MB_RTU, 0x01, 1, 115200, MB_PAR_NONE);//初始化modbus,走modbusRTU,从站地址为0x01,端口为1。
	eMBEnable();//使能modbus
	MX_RT_Thread_Init();	//初始化 RT-Thread 进程

在配置完AHT20的代码和modbus驱动文件后引入相关头文件:

#include "rtthread.h"	// RT-Thread 头文件
#include "mb.h"	// Modbus 头文件
#include "mbport.h"	// Modbus 端口头文件
#include "AHT20.h"	// AHT20传感器驱动头文件
extern void MX_RT_Thread_Init(void);	// RT-Thread 初始化函数,初始化并执行各种进程
extern void MX_RT_Thread_Process(void);	// RT-Thread 主进程

开启多线程,主任务是modbus监听,子任务是对程序进行测试:

#include "rtthread.h"
#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"
#include "stdio.h"
#include "AHT20.h"
#include "mb.h"
#include "mbport.h"
 
struct rt_thread led1_thread;
rt_uint8_t rt_led1_thread_stack[128];
void led1_task_entry(void *parameter);
 
//初始化线程函数
void MX_RT_Thread_Init(void)
{
	//初始化LED1线程
	rt_thread_init(&led1_thread,"led1",led1_task_entry,RT_NULL,&rt_led1_thread_stack[0],sizeof(rt_led1_thread_stack),3,20);
	//开启线程调度
	rt_thread_startup(&led1_thread);
}
 
//主任务
void MX_RT_Thread_Process(void)
{
	(void)eMBPoll();	//启动modbus监听
}
 
//LED1任务
void led1_task_entry(void *parameter)
{
	while(1)
	{
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13, GPIO_PIN_RESET);
		rt_thread_delay(500);
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13, GPIO_PIN_SET);
		rt_thread_delay(500);
	}

}

在 eMBRegInputCB 函数中修改功能码为04用于读取输入寄存器:

eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
	eMBErrorCode eStatus = MB_ENOERR;
	int iRegIndex;
	int i;
	InputBuff[0] = 0x11;
	InputBuff[1] = 0x22;
	InputBuff[2] = 0x33;
	InputBuff[3] = 0x44;
	
	if( ( usAddress >= REG_INPUT_START ) && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
	{
		iRegIndex = ( int )( usAddress - usRegInputStart );
		for(i=0;i<usNRegs;i++)
		{
			*pucRegBuffer=InputBuff[i+usAddress-1]>>8;
			pucRegBuffer++;
			*pucRegBuffer=InputBuff[i+usAddress-1]&0xff;
			pucRegBuffer++;
		}
	}
	else
	{
		eStatus = MB_ENOREG;
	}
 
	return eStatus;
}

在输出函数eMBRegInputCB中将传回的温湿度数据存到InputBuff[] 数组中进行输出:

eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
	eMBErrorCode eStatus = MB_ENOERR;
	int iRegIndex;
	int i;
	
	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);	// 使用 PC13 引脚上的板载小灯泡进行测试——小灯泡亮
	AHT20_Read_CTdata_crc(CT_data);       //经过CRC校验,读取AHT20的温度和湿度数据    推荐每隔大于1S读一次
	c1 = CT_data[0]*1000/1024/1024;  //计算得到湿度值c1(放大了10倍)
	t1 = CT_data[1]*2000/1024/1024-500;//计算得到温度值t1(放大了10倍)
	t2 = t1/10 + (t1/10)%10;	//温度的整数部分
	t3 = t1%10;	//温度的小数部分
	c2 = c2/10 + (c1/10)%10;	// 湿度的整数部分
	c3 = c3%10;	//湿度的小数部分
	
	InputBuff[0] = t2;
	InputBuff[1] = t3;
	InputBuff[2] = c2;
	InputBuff[3] = c3;
	
	if( ( usAddress >= REG_INPUT_START ) && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
	{
		iRegIndex = ( int )( usAddress - usRegInputStart );
		for(i=0;i<usNRegs;i++)
		{
			*pucRegBuffer=InputBuff[i+usAddress-1]>>8;
			pucRegBuffer++;
			*pucRegBuffer=InputBuff[i+usAddress-1]&0xff;
			pucRegBuffer++;
		}
	}
	else
	{
		eStatus = MB_ENOREG;
	}
 
	return eStatus;
}

由于手上没有AHT20模块无法进行效果的演示,这里只是对流程进行了大致阐述和部分重要模块代码的展示。

二、传感器仿真数据远程采集

1.TCP套接字和modbus协议

在通过TCP协议与远程数据服务建立联系的内容中主要是完成了对桥梁应力以及温度的采集。

crc校验:

def crc16(string):
    #data = bytes.fromhex(string)
    data=string
    crc = 0xFFFF
    for pos in data:
        crc ^= pos
        for i in range(8):
            if ((crc & 1) != 0):
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    return hex(((crc & 0xff) << 8) + (crc >> 8))

数据库连接:

def MySQLConnect():
    connection = pymysql.connect(
        host='localhost',  # IP,MySQL数据库服务器IP地址
        port=3306,  # 端口,默认3306,可以不输入
        user='root',  # 数据库用户名
        password='密码',  # 数据库登录密码
        database='sensor',  # 要连接的数据库
        charset='utf8'  # 字符集,注意不是'utf-8'
    )
    return connection

将数据插入到数据库:

def AddData(num,yb,wd,time):
    # 连接数据库
    conn = MySQLConnect()
    # 使用cursor()方法创建一个游标对象cursor
    cursor = conn.cursor()
    # 插入数据库
    sql = "INSERT INTO strain_sensor(id ,mic, strain_temp, time) VALUES (%s,%s,%s,%s); "
    cursor.execute(sql, [num,yb, wd, time])
    # 提交事务
    conn.commit()
    # 关闭游标
    cursor.close()
    # 关闭数据库连接
    conn.close()

获取数据:

def getStain(cmd,num,time):
    #print(cmd)
    #print(num)
    cmd = bytes.fromhex(cmd)
    crc = crc16(cmd)
    crc = bytes.fromhex(crc[2:])
    cmd = cmd + crc
    #print(cmd)
    #发送对应的指令
    tcp.send(cmd)
    try:
        data = tcp.recv(8192)
    except socket.timeout:
        print("超时")
        sys.exit(1)
    crc = data[-2:]
    crc1 = crc16(data[:-2])
    crc1 = crc1[2:]
    if len(crc1) == 3:
        crc1 = '0' + crc1
    crc1 = bytes.fromhex(crc1)
    if crc != crc1:
        print("CRC16校验失败!")
        sys.exit(2)
    yb, wd = struct.unpack('>ii', data[4:12])
    yb = yb / 100.0
    wd = wd / 100.0
    print("应变:", yb, "温度:", wd)
    print(time)
    yb = str(yb)
    wd = str(wd)
    AddData(num, yb, wd, time)

建立TCP连接:
在这里插入图片描述
在这里插入图片描述

效果:
3号传感器采集应变力和温度信息:
在这里插入图片描述
数据库:
在这里插入图片描述

2.UDP套接字和modbus协议

在使用UDP协议向远程桥梁监测数据服务系统获取数据的内容,我们实现了对温度传感器的采集以及对静力水准仪的信息采集。

CRC校验:

def crc16(string):
    #data = bytes.fromhex(string)
    data=string
    crc = 0xFFFF
    for pos in data:
        crc ^= pos
        for i in range(8):
            if ((crc & 1) != 0):
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    return hex(((crc & 0xff) << 8) + (crc >> 8))

数据库连接:

def MySQLConnect():
    connection = pymysql.connect(
        host='localhost',  # IP,MySQL数据库服务器IP地址
        port=3306,  # 端口,默认3306,可以不输入
        user='root',  # 数据库用户名
        password='password',  # 数据库登录密码
        database='sensor',  # 要连接的数据库
        charset='utf8'  # 字符集,注意不是'utf-8'
    )

将获取到的温度湿度时间戳插入到数据库中:

def AddData1(wd,sd,time):
    # 连接数据库
    conn = MySQLConnect()
    # 使用cursor()方法创建一个游标对象cursor
    cursor = conn.cursor()
    # 插入数据库
    sql = "INSERT INTO temp_hum_sensor(temp, hum, time) VALUES (%s,%s,%s); "
    cursor.execute(sql, [wd, sd, time])
    # 提交事务
    conn.commit()
    # 关闭游标
    cursor.close()
    # 关闭数据库连接
    conn.close()

获取到的传感器id、挠度、时间戳存到数据库中:

def AddData2(id,water_level,time):
    # 连接数据库
    conn = MySQLConnect()
    # 使用cursor()方法创建一个游标对象cursor
    cursor = conn.cursor()
    # 插入数据库
    sql = "INSERT INTO static_level(id, water_level, time) VALUES (%s,%s,%s); "
    cursor.execute(sql, [id, water_level, time])
    # 提交事务
    conn.commit()
    # 关闭游标
    cursor.close()
    # 关闭数据库连接
    conn.close()

温湿度采集过程(modbus):

def getDataTemp(cmd):
    #flag标志采集的次数
    flag=0
    last = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    print(last)
    last1 = time.time()
    cmd = bytes.fromhex(cmd)
    #print(cmd)
    crc = crc16(cmd)
    crc = bytes.fromhex(crc[2:])
    #得到发送的指令(modbus协议定义内容+校验)
    cmd = cmd + crc
    udp.sendto(cmd, ('demo-monitor.igong.com', 8001))
    try:
        data, addr = udp.recvfrom(8192)
    except socket.timeout:
        print("超时")
        sys.exit(1)
    crc = data[-2:]
    crc1 = crc16(data[:-2])
    crc1 = crc1[2:]
    if (len(crc1) == 3):
        crc1 = '0' + crc1
    crc1 = bytes.fromhex(crc1)

    # print(crc1)
    if crc != crc1:
        print("CRC16校验失败!")
        sys.exit(2)
    # 解析数据
    wd, sd = struct.unpack('>ii', data[4:12])
    wd = wd / 100.
    print("温度:", wd, "湿度:", sd)
    AddData1(wd, sd, last)
    flag=flag+1
    while True:
        now= time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        #print(s)
        now1=time.time()
        #每隔5s获取一次数据
        if(now1-last1>5):
            udp.sendto(cmd, ('demo-monitor.igong.com', 8001))
            try:
                data, addr = udp.recvfrom(8192)
            except socket.timeout:
                print("超时")
                sys.exit(1)
            crc = data[-2:]
            crc2=bytes.hex(crc)
            #print(crc2)
            crc1 = crc16(data[:-2])
            crc1=crc1[2:]
            if(len(crc1)==3):
                crc1='0'+crc1
            #print(crc1)
            crc1=bytes.fromhex(crc1)
            #print(crc1)
            if crc != crc1:
                print("CRC16校验失败!")
                sys.exit(2)
            #解析数据
            wd, sd = struct.unpack('>ii', data[4:12])
            wd = wd / 100.0
            #当前时间
            print(now)
            #获取得到的数据
            print("温度:", wd, "湿度:", sd)
            last=now
            last1=now1
            wd=str(wd)
            sd=str(sd)
            AddData1(wd,sd,now)
            flag = flag + 1
            if flag >= 5:
                str1 = input("请选择是否继续采集(y表示继续,n表示退出):")
                if str1 == 'y':
                    flag = 0
                    continue
                else:
                    break

在这里插入图片描述
选择传感器:

def getDataStaticLevel(cmd):
    id=cmd[0:2]
    #print(id)
    if id=='02':
        #print("2号")
        id='00'+id
        getData(id,cmd)
    elif id=='03':
        #print("3号")
        id = '00' + id
        getData(id,cmd)
    elif id=='04':
        #print("4号")
        id = '00' + id
        getData(id,cmd)
    elif id=='05':
        #print("5号")
        id = '00' + id
        getData(id,cmd)

与远程数据建立连接:
在这里插入图片描述

在这里插入图片描述
效果:
温湿度模块:
在这里插入图片描述
数据库:
在这里插入图片描述
挠度:
在这里插入图片描述
数据库:
在这里插入图片描述

三、思考题

针对实际工程应用中的多传感器、多协议、多组网方式的复杂多变的技术要求,如果采用FPGA开发板编程的灵活定制特点来设计实现不同各种接口协议,是否存在合理性?有什么优势和弊端? 请简要对比分析。

我认为是合理的,因为fpga本身编程的灵活性和数据处理的能力就足可以支撑他实现多种协议。优势:现在的中端FPGA已经在实验不同的接口协议,再者就是能够得到FPGA处理信息的能力。弊端;建立一个完整的协议栈付出会比较多,需要经过多次实验,就算通过了在信息安全方面的隐患也是存在的。


四、总结

此次方案设计的协议最主要的就是modbus了,之前的作业也有使用过,但在这一次的设计过程中就有加深了理解和熟悉。由于硬件资源的不支持,第一部分的内容主要就是根据前面实现过的作业进行一个阐述展示复习即可。在第二部分的对远程检测数据服务的连接中使用到了UDP\TCP两种连接方式,但是最主要的还是代码中实现modbus通信的实现流程的理解最为重要。所以此次设计收获满满的还是对modbus的学习!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/180901.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

readonly与disabled对比

<!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <title>readonly与disabled</title> </head> <body> <!--readonly与disabled 都是只读不能修改…

传统推荐模型(二)协同过滤的进化——矩阵分解算法

传统推荐模型&#xff08;二&#xff09;协同过滤的进化——矩阵分解算法 针对协同过滤算法的头部效应较明显、泛化能力较弱的问题&#xff0c;矩阵分解算法被提出。矩阵分解在协同过滤算法中“共现矩阵”的基础上&#xff0c;加人了隐向量的概念&#xff0c;加强了模型处理稀…

动态顺序表——简单的增删查改

前言 &#xff1a;从这篇博客开始&#xff0c;我会进行数据结构(用C语言实现)有关内容的记录与分享。对于我们而言&#xff0c;数据结构的知识难度较大并且十分重要&#xff0c;希望我的分享给各位带来一些帮助。而今天要分享的就是数据结构中最简单的知识——顺序表的增删查改…

11.Java方法的综合练习题大全-双色球彩票系统,数字的加密和解密等试题

本篇文章是Java方法的专题练习,从第五题开始难度增大,涉及大厂真题,前四道题目是基础练习,友友们可有目的性的选择学习&#x1f618;&#x1f495; 文章目录前言一、数组的遍历1.注意点:输出语句的用法2.题目正解二、数组最大值三、判断是否存在四、复制数组五、案例一:卖飞机票…

【学习笔记之数据结构】二叉树(一)

二叉树的概念&#xff1a; 二叉树是一种树的度不大于2的树&#xff0c;也就是它的节点的度都是小于等于2的。二叉树的子树有左右之分&#xff0c;左右的次序不能颠倒&#xff0c;因此二叉树是一个有序树。任意的二叉树都由空树、只有根节点、只有左子树、只有右子树、左右子树均…

一个简单的自托管图片库HomeGallery

什么是 HomeGallery &#xff1f; HomeGallery 是一个自托管的开源 Web 图片库&#xff0c;用于浏览个人照片和视频&#xff0c;其中包括标记、对移动端友好和 AI 驱动的图像和面部发现功能。 HomeGallery 的独特功能是自动 相似图像/反向图像搜索功能 和 无数据库架构 &#x…

实验三、8人智力竞赛抢答电路设计

实验三 8人智力竞赛抢答电路设计 实验目的 设计一个能支持八路抢答的智力竞赛抢答器&#xff1b;主持人按下开始抢答的按键后&#xff0c;有短暂的报警声提示抢答人员抢答开始且指示灯亮表示抢答进行中&#xff1b;在开始抢答后数码管显8秒倒计时&#xff1b;有抢答人员按下抢…

Linux企业应用现状

一、Linux在服务器领域的发展 随着开源软件在世界范围内影响力日益增强&#xff0c;Linux服务器操作系统在整个服务器操作系统市场格局中占据了越来越多的市场份额&#xff0c;已经形成了大规模市场应用的局面。并且保持着快速的增长率。尤其在政府、金融、农业、交通、电信等国…

linux 网络编程socket

前言 socket&#xff08;套接字&#xff09;是linux下进程间通信的一种方式&#xff0c;通常使用C-S&#xff08;客户端-服务端&#xff09;的方式通信&#xff0c;它可以是同一主机下的不同进程间通信或者不同主机的进程通信。 socket是夹在应用层和TCP/UDP协议层间的软件抽象…

机器自动翻译古文拼音 - 将进酒拼音版本,译文拼音版本

写了一个程序&#xff0c;用来给佛经和古诗加上拼音&#xff0c;并处理多音字和排版&#xff0c;顺便加上翻译。 定期翻译一些&#xff0c;给老人和小孩子用。 将进酒 君不见&#xff0c;黄河之水天上来&#xff0c;奔流到海不复回。 君不见&#xff0c;高堂明镜悲白发&…

Servlet介绍及其概念

Servlet介绍及其概念一、Web基础二、编写HTTP Server&#xff0c;打印Hello,World三、Servlet的出现1. 思考上述HTTP服务器的问题2. 实现代码重用&#xff0c;简化开发过程3. 实现最简单的Servlet4. 导入依赖5. pom.xml文件6. Servlet版本问题7. 整个Servlet工程结构四、运行Se…

Windows卸载与清除工具 “ Geek 与 CCleaner ”

前言 &#x1f4dc;“作者 久绊A” 专注记录自己所整理的Java、web、sql等&#xff0c;IT技术干货、学习经验、面试资料、刷题记录&#xff0c;以及遇到的问题和解决方案&#xff0c;记录自己成长的点滴 目录 前言 一、Geek的简介 1、大概介绍 2、详细介绍 二、Geek的下载 1、…

千峰Ajax【fetch和promise】

promise基础 <script>// Promise构造函数var q new Promise(function (resolve, reject) {//异步setTimeout(function () {// 成功// resolve(["111", "222", "333"]);// 失败reject("error");}, 2000);});// q是promise对象q…

利用系统函数与堆栈快速定位app关键代码

string.trim 这个还是比较关键的&#xff0c;没准可以从这里得到加密方式&#xff0c;或者挖到sql注入&#xff0c;文件上传等漏洞。进一步利用可以打印堆栈来用 Java.perform(function(){function showStack(){console.log(Java.use("android.util.Log").getStack…

TCP/IP网络编程——基于 TCP 的服务端/客户端(下)

完整版文章请参考&#xff1a; TCP/IP网络编程完整版文章 文章目录第 5 章 基于 TCP 的服务端/客户端&#xff08;2&#xff09;5.1 回声客户端的完美实现5.1.1 回声服务器没有问题&#xff0c;只有回声客户端有问题&#xff1f;5.1.2 回声客户端问题的解决办法5.1.3 如果问题不…

chrome插件开发时使用import

问题描述 在进行chrome插件开发时&#xff0c;我们有时会希望把一些公共的方法包装成一个模块&#xff0c;例如发送网络请求的方法&#xff0c;然后在其他js文件中import然后调用&#xff0c;但是在实际操作时&#xff0c;遇到了这样的问题&#xff1a; 控制台报错cannot use …

Vistual Studio Code 安装与配置C/C++环境

1. 下载VScode 2. 安装cpptools工具 3. 下载MinGW 4. 配置环境变量 5. 使用简单的.cpp文件配置C环境 6. 运行 注&#xff1a;本文所有的地址配置要根据读者的实际情况来&#xff0c;不要照文章复制&#xff01;&#xff01;&#xff01; 下载VScode 下载链接&#xff1a;https…

浏览器调用本地DLL的方法

要在浏览器中调用本地DLL&#xff0c;常见的方法是使用插件。但是为了安全&#xff0c;现在有的浏览器对插件开发做了限制&#xff0c;不让插件调用外部DLL。比如说Chrome&#xff0c;为了调用外部的DLL&#xff0c;我们只能使用早期的chrome版本。 还有一种方法就是在电脑上安…

linux编辑器的使用(gcc,g++)

前言 gcc/g是一个编译器。 我们程序的翻译有四个步骤1.预处理(头文件展开&#xff0c;条件编译&#xff0c;宏替换&#xff0c;去注释)2.编译(c语言汇编语言)3.汇编(汇编->可重定位目标二进制文件&#xff0c;不可以被执行的&#xff0c;bin.obj)----只是把我们自己的代码进…

下载Windows ISO镜像的方法 (超详细 适合新手入门)

前言 &#x1f4dc;“作者 久绊A” 专注记录自己所整理的Java、web、sql等&#xff0c;IT技术干货、学习经验、面试资料、刷题记录&#xff0c;以及遇到的问题和解决方案&#xff0c;记录自己成长的点滴 目录 前言 一、镜像介绍 1、大概介绍 2、详细介绍 二、下载Window…