尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
STM32与EC20 4G模块AT指令联调:从硬件连接到TCP透传上云
简介面向STM32F207开发者的一份EC20 4G/LTE模块AT指令驱动源码包适合物联网设备中需要快速实现串口指令交互、网络附着与数据收发的嵌入式工程师。代码按功能拆分共6个文件含3个C源文件与3个头文件分别对应驱动主逻辑、消息环形队列和通用工具函数压缩包仅15KB结构紧凑便于移植到FreeRTOS或其他STM32工程。已有3910人学习下载。资源重点解决了AT指令发送与响应解析、接收缓存管理、掉线重连与复位引脚控制等实际问题并包含错误处理与状态管理逻辑可在串口中断中接收EC20返回内容以OK/ERROR等关键字判断执行结果开发者可直接基于HAL库配置UART快速完成EC20模块初始化、GPRS附着与数据收发。对正在搭建4G通信链路或需要参考模块化驱动设计的工程师而言这份小体积源码有较高复用价值。1. 基于STM32的AT指令操作EC20模块从裸机联调到透传上云的完整落地做物联网项目最怕的不是写代码而是设备死活连不上网。EC20模块这类的4G Cat-4方案凭借成熟的AT指令集和广泛的运营商兼容性几乎成了工业网关和遥测终端的标配。它的核心玩法并不复杂——STM32通过串口向模块发送文本指令模块回传响应你来解析状态。真正让新手反复翻车的是SIM卡识别失败、网络注册超时、透传模式退出逻辑这几个环节资源包里通常已经整理好现成的驱动框架你要做的不是重写而是把底层的时序和超时策略理解透。这篇笔记适合正在调4G模块的嵌入式开发者也适合准备把设备数据搬上云端的工程师按照我们一步步来能帮你省下至少一周的调试时间。2. EC20模块与STM32的硬件连接引脚定义、电平匹配和开机时序2.1 EC20模块的关键引脚与供电设计拿到EC20模块的硬件手册第一件事不是看AT指令列表而是确认供电和电平。EC20工作电压范围是3.3V到4.3V典型值3.8V峰值电流在2A左右这意味着一颗线性稳压芯片很难扛住瞬态功耗。某开发者的第一版板子用了AMS1117-3.3直接供电结果一呼叫就复位最后换成MP1584降压模块加470uF电解电容才稳定。我一般会在靠近模块VBAT引脚的地方并联两个电容100uF钽电容加0.1uF陶瓷电容分别应对低频纹波和高频噪声。USB_VBUS引脚可以用于模块的USB枚举但在纯AT指令控制场景下不需要连接。模块的主串口是UART1或者叫Main UART默认波特率1152008位数据位无校验1位停止位。部分模组厂商会在出厂时把波特率改成9600第一次连接时如果没反应可以先试一遍常用波特率。电平平匹配是另一个高频坑点。EC20的串口电平是1.8V而STM32F103系列默认是3.3V直接相连轻则通信不稳定重则烧毁模块IO口。推荐方案是加一颗TXS0108EPWR电平转换芯片或者用两颗MOS管搭双向电平转换电路。连接关系按下面这张表来STM32引脚电平转换方向EC20引脚说明PA2 (USART2_TX)3.3V → 1.8VUART1_RX主串口接收PA3 (USART2_RX)1.8V → 3.3VUART1_TX主串口发送PA43.3V → 1.8VPWRKEY开机控制PA53.3V → 1.8VRESET硬件复位GND-GND共地必须接注意PWRKEY引脚内部有上拉外部要接一个开漏输出或三极管控制直接推挽输出可能导致开机后无法拉低实现关机。2.2 开机时序为什么你的模块发送AT没反应EC20的开机不是上电即启动它需要PWRKEY引脚被拉低一段时间。参考手册的时序要求是PWRKEY拉低持续600ms以上然后释放模块开始内部初始化大约2到3秒后串口会打印一次开机日志内容可能是RDY或者^SYSSTART。很多人的代码里上电后立刻发AT自然得不到响应。正确顺序是先初始化STM32的GPIO和串口然后拉低PWRKEY 800ms再等待模块主动输出启动标志。我习惯在串口接收中断里检测^SYSSTART字符串检测到之后再延时500ms然后发送第一条AT指令做握手。这个流程写成代码大概是void EC20_PowerOn(void) { HAL_GPIO_WritePin(PWRKEY_GPIO_Port, PWRKEY_Pin, GPIO_PIN_RESET); HAL_Delay(800); HAL_GPIO_WritePin(PWRKEY_GPIO_Port, PWRKEY_Pin, GPIO_PIN_SET); // 等待模块主动上报启动事件超时10秒 uint32_t tick HAL_GetTick(); while ((HAL_GetTick() - tick) 10000) { if (ec20_boot_flag) { // 在串口回调中置1 HAL_Delay(500); return; } HAL_Delay(10); } // 超时未收到启动标志仍尝试发送握手指令 EC20_SendCommand(AT\r\n, 300); }这段逻辑里没有死等某个字符串而是用一个标志位来判断。很多量产固件不会依赖启动日志因为不同固件版本的输出内容可能有差异把AT握手命令作为最终兜底更稳妥。超时时间10秒被一些人改到30秒实际上模块在信号正常的环境下最多5秒就会就绪过长只会拖慢开机流程。2.3 串口初始化与DMA接收缓冲设计EC20的响应结构是典型的“不定长字符串”可能一条指令回几十字节也可能隔几秒主动上报URC消息比如QURCC: 0。如果用中断逐字节接收然后拼字符串逻辑简单但容易在高速率下丢失数据。我采用的方法是串口DMA接收空闲中断配合环形缓冲区DMA把数据搬进256字节数组空闲中断触发后把当前已接收长度交给解析器。uint8_t uart_rx_buf[256]; volatile uint16_t uart_rx_len 0; void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *UartHandle, uint16_t Size) { if (UartHandle-Instance USART2) { uart_rx_len Size; EC20_ParseBuffer(uart_rx_buf, uart_rx_len); HAL_UARTEx_ReceiveToIdle_DMA(huart2, uart_rx_buf, 256); } }这里用HAL_UARTEx_ReceiveToIdle_DMA替代传统的HAL_UART_Receive_IT好处是CPU占用极低只要串口空闲超过一个字节时间就会触发回调。注意一个细节EC20的波特率是115200一个字节约87us空闲判定大约是87us到174us之间DMA的IDLE中断能满足这个节奏。3. AT指令初始化流程从握手到网络注册的完整命令序列3.1 基础握手与版本信息获取EC20的AT指令体系基于3GPP TS 27.007标准同时扩展了Quectel私有指令。整个初始化过程建议按固定顺序执行不要跳跃。第一步自然是发AT模块会返回OK。如果这一步失败后面所有操作都没有意义。发送: AT\r 接收: OK 发送: ATI\r 接收: Quectel EC20EFDKGGR Revision: EC20EFDKGGR06A05M1G OKATI返回的内容里包含了模组型号、固件版本、功能支持情况这些信息在排查问题时非常有用。某开发者手里有两块标注相同型号的EC20但ATI结果不同——一个是LTE-only固件一个是LTEWCDMA固件这直接影响了后续网络注册的行为。固件版本差异可能导致某些私有AT指令不可用务必记录下模块出厂信息。3.2 SIM卡检测为什么电话卡插上却报错EC20检测SIM卡使用ATCPIN?命令正常返回CPIN: READY。如果返回CME ERROR: 10表示SIM卡未插入或接触不良返回CME ERROR: 13则是卡已插入但尚未准备好需要重新上电或复位模块。发送: ATCPIN?\r 接收: CPIN: READY OK资源里有些代码会在开机流程中循环查询此命令直到READY但没考虑一个边界情况如果卡槽里根本没有SIM卡这个查询会永远失败导致初始化卡死。正确做法是设置查询次数上限比如15次每次间隔1秒超过就跳过继续走网络注册流程同时把SIM状态上报给应用层。返回值含义处理建议CPIN: READY卡已就绪继续后续流程CME ERROR: 10未插入SIM卡检查卡座焊接和卡槽方向CME ERROR: 13SIM卡未就绪等待几秒后重试CME ERROR: 14SIM卡被锁需要发送PUK码解锁3.3 信号质量查询与网络注册状态判断信号质量用ATCSQ查看返回值包含RSSI接收信号强度和BER误码率。RSSI最大31对应的dBm范围是从-51dBm到-113dBm数值越大信号越好。一个常见的认知误区是认为RSSI返回31就是满格满速实际上如果模块待在实验室里靠近窗口RSSI通常只有15到20。网络注册状态通过ATCREG?查询返回CREG: 0,1表示已注册上LTE网络其中第二个参数1代表“已注册归属网络”如果是5则代表“已注册漫游”。调试时建议把第一个参数设为1即ATCREG1这样当网络状态发生变化时模块会主动上报CREG的URC消息方便追踪掉线原因。发送: ATCSQ\r 接收: CSQ: 18,0 OK 发送: ATCREG?\r 接收: CREG: 0,1 OKCSQ返回18对应的信号强度大约-75dBm到-77dBm属于正常范围。如果CSQ一直等于99说明模块搜不到网络可能是天线没接好、SIM卡欠费、或者所处位置信号盲区。排除顺序是先检查天线座是否拧紧再确认SIM卡的APN配置最后用ATQENGservingcell查看模块当前搜索到的具体小区信息。3.4 PDP上下文激活拨号上网前的最后一步LTE模块上网需要先激活PDP上下文对应命令是ATCGDCONT设置APN然后ATQIACT激活。不同运营商的APN不一样最常见的是cmnet、ctnet和3gnet但有些物联卡使用专用APN比如cmiot。如果使用了错误的APN模块虽然能注册网络但无法建立数据连接。发送: ATCGDCONT1,IP,cmnet\r 接收: OK 发送: ATQIACT\r 接收: OK 发送: ATQIACT?\r 接收: QIACT: 1,1,1,10.142.182.36 OKATQIACT?最后的10.142.182.36是模块从网络获取的IP地址有IP说明PDP上下文激活成功。注意QIACT: 1,1,1,...中第二个参数是激活状态1代表已激活如果返回0则激活失败。此时用ATQIGETERROR获取真正的错误码常见的是601PDN激活拒绝多为APN错误或603网络不支持。3.5 完整的初始化命令封装把以上流程封装成一个带状态机的初始化函数效果比逐个指令硬编码好得多。每个步骤对应一个枚举状态在串口响应回调中根据当前状态跳转下一个命令。typedef enum { EC20_STATE_AT 0, EC20_STATE_CPIN, EC20_STATE_CSQ, EC20_STATE_CREG, EC20_STATE_CGDCONT, EC20_STATE_QIACT, EC20_STATE_READY } EC20_State_t; EC20_State_t ec20_state EC20_STATE_AT; uint8_t creg_timeout 0; void EC20_StateMachine(char *response) { switch (ec20_state) { case EC20_STATE_AT: if (strstr(response, OK)) { ec20_state EC20_STATE_CPIN; EC20_SendCommand(ATCPIN?\r\n, 1000); } break; case EC20_STATE_CPIN: if (strstr(response, READY)) { ec20_state EC20_STATE_CSQ; EC20_SendCommand(ATCSQ\r\n, 1000); } else { // 重试逻辑 EC20_SendCommand(ATCPIN?\r\n, 1000); } break; // 后续状态类似 } }这段代码的价值不在实现细节而在状态跳转的严谨性。每个状态都要考虑超时和重试次数否则一个临时网络异常就会让整个初始化流程阻塞。资源包里通常还有一套相似的框架你可以对比一下各自的超时参数设置——这往往是移植时最容易忽略的部分。4. STM32端AT指令解析与数据收发环形缓冲区、响应匹配与超时机制4.1 为什么不能用简单的strstr匹配响应EC20的响应具有不确定性一个ATQIOPEN指令可能立即返回OK也可能隔几十秒才返回QIOPEN: 0,0中间还可能插入QURCC: 0这样的URC上报。如果用阻塞式的等待串口接收缓冲区会被塞满后续数据直接丢失。正确的思路是“收到数据就解析匹配到目标就置标志位”而不是“循环等待字符串出现”。typedef struct { uint8_t buf[512]; uint16_t len; uint32_t start_time; uint8_t busy; } EC20_CmdContext_t; EC20_CmdContext_t cmd_ctx; int EC20_WaitResponse(const char *expected, uint32_t timeout_ms) { cmd_ctx.busy 1; cmd_ctx.len 0; memset(cmd_ctx.buf, 0, 512); cmd_ctx.start_time HAL_GetTick(); while ((HAL_GetTick() - cmd_ctx.start_time) timeout_ms) { if (cmd_ctx.len 0) { if (strstr((char*)cmd_ctx.buf, expected)) { cmd_ctx.busy 0; return 1; } if (strstr((char*)cmd_ctx.buf, ERROR) || strstr((char*)cmd_ctx.buf, CME ERROR)) { cmd_ctx.busy 0; return -1; } } HAL_Delay(10); } cmd_ctx.busy 0; return 0; // 超时 }这里用了一个512字节的命令上下文缓冲区来存储本次命令的完整响应。注意查询用的是strstr而不是比较整串因为模块可能会在期望字符串前后附加额外信息比如QIOPEN: 0,0中的连接ID就是动态的。4.2 环形缓冲区设计不丢数据的接收基础在串口中断层面每收到一个字节就拷贝到环形缓冲区解析线程定时从缓冲区取数据。这个设计常见但EC20的URC消息会随时插入导致解析状态机的输入不是一个完整命令序列。#define RING_BUF_SIZE 1024 typedef struct { uint8_t buffer[RING_BUF_SIZE]; volatile uint16_t head; volatile uint16_t tail; } RingBuffer_t; RingBuffer_t ec20_rx_ring; void EC20_UART_RxCpltCallback(uint8_t byte) { uint16_t next (ec20_rx_ring.head 1) % RING_BUF_SIZE; if (next ! ec20_rx_ring.tail) { ec20_rx_ring.buffer[ec20_rx_ring.head] byte; ec20_rx_ring.head next; } // 缓冲区满时丢弃新数据避免覆盖未读内容 }环形缓冲区的容量选择很关键。EC20在弱信号环境下可能连续上报多条QURCC或者QGPSENGINE消息每条几十上百字节如果缓冲区只有256字节一天的运行时间内出现丢数据几乎是必然的。我一般配到1024字节并在解析时优先处理URC类型消息。4.3 区分同步响应与异步URC消息ATQHTTPREAD这类命令返回的数据可能长达几百字节而QURCC: 1这样的URC消息会随时主动弹出。如果在等待前者的过程中收到后者直接丢弃会丢失关键状态信息错误处理则会让解析逻辑变得复杂。常见做法是在任何接收处理函数里先判断当前收到的字符串是否以开头如果是则检查是否为已知的URC消息不是就丢弃是就走独立回调。void EC20_ProcessReceivedData(uint8_t *data, uint16_t len) { if (data[0] ) { // 处理URC消息 if (strncmp((char*)data, QURCC, 6) 0) { EC20_HandleQurcc(data, len); return; } if (strncmp((char*)data, QIURC, 6) 0) { EC20_HandleQiurc(data, len); return; } } // 其他情况归入当前命令的响应缓冲区 memcpy(cmd_ctx.buf[cmd_ctx.len], data, len); cmd_ctx.len len; }这段代码能工作前提是你对EC20可能上报的URC消息类型心中有数。模块手册里有一张URC索引表其中QURCC是用于FTP或HTTP下载的进度上报QIURC是TCP/UDP相关的事件通知。如果项目不做TCP透传这些消息可以简单忽略但如果做了每条都必须正确处理。5. 避坑指南EC20调试中常见的六个翻车场景与排查方法5.1 现象发送AT指令无响应模块像死了一样这是最高频的问题。可能的原因有四种模块没正常开机、串口引脚接错、波特率不匹配、电平不匹配。按顺序排查先测量VBAT电压是否稳定再确认PWRKEY低电平持续时间是否超过600ms然后检查STM32的串口是否配置正确最后用逻辑分析仪抓取TX线是否有数据输出。某开发者遇到过一种隐蔽情况模块的串口TX和STM32的RX用杜邦线相连杜邦线接触不良偶尔能通偶尔不通。解决方法是直接焊死或者至少按压确认接触可靠。硬件调试阶段每个连接点都是潜在的故障源。5.2 现象SIM卡检测经常失败提示CME ERROR: 13CME ERROR: 13的官方解释是SIM卡未就绪这种错误在冷启动时偶尔出现属于正常。但如果每次上电都失败就要检查卡座设计EC20模块对SIM卡座的ESD防护要求较高卡座DATA引脚上必须加ESD保护器件否则插拔瞬间的静电会干扰SIM卡时钟信号。另外SIM卡座的VCC和GND之间要加0.1uF去耦电容位置尽量靠近卡座。一个容易被忽略的原因是SIM卡的金属触点氧化。工程样机上经常用到旧卡触点发黑导致接触电阻偏大。遇到顽固的SIM卡检测问题先用万用表测卡座的VCC和GND是否正常RST和CLK引脚能否测到脉冲。5.3 现象ATQIACT激活失败返回601错误这个错误码的含义是PDN激活被核心网拒绝。排除顺序是先确认APN是否填写正确很多物联卡需要专属APN不能用常规的公网APN找运营商索要APN配置是首选然后确认SIM卡是否已经开通数据业务部分卡默认只支持短信不支持上网最后检查模块是否已经成功注册到LTE网络没有注册就激活PDP上下文必然失败。调试时使用ATQENGservingcell查看模块的当前服务小区和网络制式如果显示LTE说明已经注册成功显示No Service则继续排查信号问题。5.4 现象数据传输一段时间后掉线且无法自动重连EC20在低信号环境下TCP连接可能被网络侧释放模块会触发QIURC: 1,0之类的URC消息。很多人只在应用层做了TCP重连逻辑没有处理模块自身的网络附着状态变化。当模块从LTE掉到GSM网络或者PDP上下文被网络去激活应用层重连TCP是徒劳的。正确做法是监控模块的QIMBAND或QNWPREFCFG配置固定使用LTE Only模式避免网络制式切换带来的断流。固定制式需要发送ATQNWPREFCFGmode_pref,7其中7代表LTE Only。注意不同固件版本对这个参数的定义略有差异模块固件在ATI返回中可以看到版本号需要对照该版本的命令手册修改。5.5 现象透传模式下退出不了返回不了命令模式EC20进入透传模式用的指令是ATQISWTMD1退出方式是发送。但有个细节字符必须前后都有0.5秒以上的时间间隔且这1.5秒内不能有其他数据发送模块才会识别为退出序列。很多代码里直接在透传循环中一条printf()了事自然没有效果。退出序列在日志中会显示为NO CARRIER或者直接回到AT模式随后发送ATO可以重新进入透传模式。这个机制本是用来在透传数据流中区分控制指令的误触发的概率不低因此在应用层协议设计时要对数据内容的序列做转义或分帧处理。5.6 现象开机时模块偶尔无法启动复位后恢复正常这通常是硬件问题而非软件逻辑问题。EC20的开机电流峰值很大如果电源适配器输出功率不足模块在内部射频PA启动瞬间电压跌落导致启动失败。解决方法是更换更大功率的电源或者检查VBAT端的供电走线宽度至少2mm宽。另一个原因是PWRKEY释放太早GPIO配置成开漏输出后需要驱动三极管基极来拉低PWRKEY三极管本身存在导通延迟如果软件延时刚好卡在临界值就会出现偶发失败。解决办法是把延时从600ms提高到800ms到1秒留够余量。6. 进阶玩法TCP透传与MQTT接入的实现要点和调试技巧TCP透传是EC20模块最常用的数据通道配合MQTT协议可以快速搭建物联网数据上报链路。EC20没有内置MQTT协议栈需要在STM32端实现MQTT客户端逻辑通过TCP socket连接云端。先建立TCP连接使用ATQIOPEN指令发送: ATQIOPEN1,0,TCP,203.0.113.10,1883,0,0\r 接收: OK QIOPEN: 0,0第二个返回参数0代表连接ID后续收发数据都用这个ID。连接建立后切换到透传模式发送MQTT报文或者直接在AT模式下用ATQISEND0一条一条发送。通常情况下数据量小用AT模式逐条发送更稳定数据量大则用透传模式效率更高。// MQTT连接报文构建示例 uint8_t mqtt_connect[64]; uint16_t len 0; mqtt_connect[len] 0x10; // CONNECT报文类型 // 可变头部的剩余长度需要计算这里省略 memcpy(mqtt_connect[len], MQTT, 4); len 4; mqtt_connect[len] 0x04; // 协议级别 mqtt_connect[len] 0x02; // 连接标志设置Clean Session // ... 后续填充ClientID和KeepAlive EC20_SendATData(0, mqtt_connect, len);整个流程中最关键的调试点是MQTT报文构造。如果用在线工具生成报文做比对注意工具生成的报文默认带用户名和密码字段而你的嵌入式代码里可能没设置连接标志位必须对得上。另一个容易出错的地方是剩余长度字段的编码大于127的报文长度需要采用变长编码按MQTT规范处理。验证设备是否成功接入云端直接在MQTT服务器端订阅对应主题观察是否有设备上报的报文。EC20侧的调试用ATQISEND0,0设置TCP发送超时避免网络缓冲区满导致长时间阻塞。我在那次超低功耗的遥测终端项目里把所有AT指令的发送和解析做成一个独立的驱动模块状态机的每个跳转都记录在Flash日志里现场设备出现异常时直接读日志定位到具体是哪个环节卡住。从那以后每次调试新的EC20固件版本我都强制走一遍完整的初始化时序并把ATI输出、ATCSQ、ATCREG?的结果打印在串口助手的第一屏这样的习惯无论是开发还是去现场排障都帮我省去了大量盲猜的时间。希望这篇笔记能让你少走些弯路顺利把EC20跑起来。本文还有配套的精品资源点击获取
RELATED

相关推荐

CBAM注意力机制与CNN故障检测:从原理到PyTorch实战全指南

CBAM注意力机制与CNN故障检测:从原理到PyTorch实战全指南

1. 项目整体设计与需求拆解1.1 这个课题到底要解决什么问题先说结论:这个题目给的场景很“标准”,但特别容易做偏。很多同学一拿到“机器学习基于CBAM-CNN的故障汽车检测”这种题目,第一反应是去找个宝马、奥迪的图片数据集,然后闷…

📅 2026/10/19 17:05:12
开源 CLI 代码审查工具:基于 Git 与本地 LLM 的轻量级自检方案

开源 CLI 代码审查工具:基于 Git 与本地 LLM 的轻量级自检方案

1. 项目概述:一个真正能落地的开源代码审查 CLI 工具“open-code-review”这个名字乍看平平无奇,但拆开来看——open不是指“开源”,而是指“开放上下文”;code-review也不是走形式的 PR 点赞,而是让大模型真正理解你改…

📅 2026/10/19 17:05:11
老毛桃v7.0 UEFI启动盘制作全指南:解决双模式识别失败

老毛桃v7.0 UEFI启动盘制作全指南:解决双模式识别失败

简介:老毛桃U盘启动盘制作工具(UEFI版 装机版)v7.0是一款面向电脑初学者与系统维护人员的轻量级系统辅助工具,专为快速制作兼容UEFI与传统BIOS的U盘启动盘、安装原版Windows系统及执行PE环境下的系统维护任务而设计。资源包共2个文…

📅 2026/10/19 17:00:11
MORE NEWS

更多资讯

📰

多智能体并非越多越好:Brooks定律下的AI Agent效率陷阱

前阵子我在做一个自动化分析工具,一开始脑热,把整个流程拆成了六个AI智能体:一个负责读数据,一个负责总结,一个负责提建议,一个负责审查,还有一个负责编排,最后还配了个"兜底&q…

📰

用Dify零代码实现双模型分栏同步流式输出,替代OpenWebUI

把 OpenWebUI 换成 Dify 做双模型分栏同步流式输出,是最近我搭内部演示工具时反复验证过的一条路。OpenWebUI 大家都很熟,界面简洁、多模型同屏输出也没问题,但真到业务场景里,我想要的是一个输入框发出去,两个模型同时…

📰

AI重塑神经科学:数据处理、模型选型与避坑实战指南

1. 从AI for Science说起:神经科学为什么是下一块硬骨头最近这几年,AI for Science从一个挂在嘴边的概念,逐渐变成了实打实的研究工具。蛋白质结构预测、材料筛选、基因组学这些方向,AI已经跑在前面,甚至成了不少实验室…

📰

7-Zip安装教程:从下载到使用的干净解压软件完全指南

说实话,现在电脑上想找个“干净”的解压软件,比找一部好剧还难。满屏的“高速下载”按钮、弹窗广告、捆绑安装,一不小心就把全家桶请进家门。所以当我看到“7-Zip安装教程”这个词条时,第一反应就是:终于有人在认真推荐…

📰

文件包含漏洞实战:从LFI到RFI再到日志注入与图片马组合利用

文件包含漏洞这种问题,刚接触 Web 安全时我总觉得它很低级:无非就是 include 了一个用户传进来的参数。直到在一套开源靶场里把文件包含模块从低到高全刷了一遍,才发现里面的细节比想象中多很多。本地包含、远程包含、伪协议读源码、日志注入…

📰

基于书评文本的推荐系统:Java实现标签提取与相似度匹配

简介:一套基于网络书评文本内容的个性化书籍推荐系统设计源码,面向Java开发者、推荐系统研究者及自然语言处理入门者,解决如何从大量书评中甄别有效评论、构建书籍标签集并计算标签关联度,以实现内容精准匹配的问题。压缩包共40个…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬