物联网网关Web服务器--CGI开发实例BMI计算
本例子通一个计算体重指数的程序来演示Web服务器CGI开发。
硬件环境:飞腾派开发板(国产E2000处理器)
软件环境:飞腾派OS(Phytium Pi OS)
硬件平台参考另一篇博客:国产化ARM平台-飞腾派开发板硬件与系统
lighttpd服务器部署参考另一篇博客:物联网网关Web服务器--lighttpd服务器部署与应用测试
1、部署与运行效果
//启动服务器
user@phytiumpi:/var/www$ sudo service lighttpd start//服务器根目录/var/www部署如下目录与文件
user@phytiumpi:/var/www$ tree
.
`-- html|-- bmi.png|-- bmi_index.png|-- cgi-bin| `-- bmi.cgi`-- index.html2 directories, 4 files//文件权限如下
user@phytiumpi:/var/www$ ls -lh html/*
-rw-r--r-- 1 root root 36K Jan 16 11:07 html/bmi.png
-rw-r--r-- 1 root root 13K Jan 16 14:08 html/bmi_index.png
-rw-r--r-- 1 root root 688 Jan 16 11:07 html/index.htmlhtml/cgi-bin:
total 16K
-rwxr-xr-x 1 root root 15K Jan 16 13:51 bmi.cgi//bmi.cgi文件类型
user@phytiumpi:/var/www$ file html/cgi-bin/bmi.cgi
html/cgi-bin/bmi.cgi: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=f39d7a4a7551ef3e3b4eba59a12959d4bc636032, for GNU/Linux 3.7.0, not stripped
-
浏览器运行
输入身高与体重信息,点击“计算”按钮,会提交当前网页中的表单数据到Web服务器并返回计算后的BMI数据。
2、Index网页文件说明
index.html是web服务器默认的页面文件,主要作用就是显示一个静态页面,提交当前页面后指定的cgi程序执行处理。
//action 指定了cgi-bin\bmi.cgi为提交后执行的程序文件
<form action="cgi-bin\bmi.cgi" method="get">
index.html源码:
<html>
<body>
<div align="center">
<form action="cgi-bin\bmi.cgi" method="get"> <table> <tr><td rowspan="3"><img src="bmi.png" hight="60" width="120"></td><td align="center" colspan="3"><h2>体重指数(BMI)计算器</h2></td></tr><tr><td >身高 : <input type="number" name="cm" min="1" max="300" size="3"> cm </td><td >体重 : <input type="number" name="kg" min="1" max="500" size="3"> kg </td><td align="center" ><input type=submit value=" 计 算 " size="16"> </td></tr><tr><td align="center" colspan="3">BMI = <input type="text" name="ret" value="" size="3" readonly></tr> </table>
</form>
</br><img src=bmi_index.png >
</div>
</body>
</html>
3、HTTP 请求处理功能说明
通过getvalue.h头文件实现。
宏定义和全局变量
#define FIELD_LEN 60
#define NV_PAIRS 15 typedef struct name_value_st{char name[FIELD_LEN + 1];char value[FIELD_LEN + 1];
} name_value;name_value name_val_pairs[NV_PAIRS];
int num_pairs = 0;/*pairs number*/
const char *M = NULL;
const char *L = NULL;
const char *S = NULL;
static int iread = 0;
-
FIELD_LEN
宏定义了每个名称或值的最大长度为 60。 -
NV_PAIRS
宏定义了可以处理的名称 - 值对的最大数量为 15。 -
name_value
结构体包含两个字符数组name
和value
,分别用于存储名称和值,长度为FIELD_LEN + 1
。 -
name_val_pairs
是name_value
结构体的数组,用于存储多个名称 - 值对。 -
num_pairs
用于记录实际存储的名称 - 值对的数量。 -
M
、L
、S
是指向常量字符的指针,初始化为NULL
,可能用于存储请求方法、内容长度和查询字符串。 -
iread
是静态整型变量,可能用于记录读取值的次数。
函数声明
void unescape_url(char *url);
void set_env(const char *r_mth, const char *c_len,const char *q_str);
char* get_value(const char *name);
int get_input(void);
void send_error(char *error_test);
char x2c(char *what);
void load_nv_pair(char *tmp_buffer, int nv_entry_number_to_load);
-
unescape_url(char *url)
:对 URL 进行转义处理。 -
set_env(const char *r_mth, const char *c_len,const char *q_str)
:设置环境变量,将传入的三个参数存储到全局指针M
、L
和S
中。 -
get_value(const char *name)
:根据传入的名称查找并返回对应的value
。 -
get_input(void)
:获取输入数据,根据请求方法(POST 或 GET)将数据存储在ip_data
中,并将数据解析为名称 - 值对存储在name_val_pairs
中。 -
send_error(char *error_text)
:输出错误信息,以 HTML 格式输出错误信息。 -
x2c(char *what)
:将十六进制表示的字符转换为对应的 ASCII 字符。 -
load_nv_pair(char *tmp_buffer, int nv_entry_number_to_load)
:将tmp_buffer
中的名称 - 值对加载到name_val_pairs
数组的指定条目中。
set_env(const char *r_mth, const char *c_len,const char *q_str)
void set_env(const char *r_mth, const char *c_len,const char *q_str)
{M = r_mth;L = c_len;S = q_str;
}
-
功能:将传入的三个参数
r_mth
、c_len
和q_str
分别赋值给全局指针M
、L
和S
,用于存储环境信息。
get_value(const char *name)
char* get_value(const char *name)
{int nv_entry_number = 0;int i = 0;char* val = NULL;char *tname = NULL;if(iread == 0){ if (!get_input()){return "error";exit(EXIT_FAILURE);}}for(i = 0; i < num_pairs; i++ ){ val = name_val_pairs[nv_entry_number].value;tname = name_val_pairs[nv_entry_number].name;nv_entry_number++;if( strcmp(tname,name) == 0 ){ break;}else{ val = NULL; tname = NULL;}}iread++;//read value timesreturn val; exit(EXIT_SUCCESS);
}
-
功能:
-
首先,如果
iread
为 0,则调用get_input()
函数获取输入数据。如果get_input()
失败,返回"error"
并终止程序。 -
然后遍历
name_val_pairs
数组,比较每个名称 - 值对的名称部分和传入的name
,如果匹配,将对应的value
存储在val
中。 -
增加
iread
的值,表示读取值的次数。 -
最后返回找到的
value
,如果未找到,返回NULL
。
-
get_input(void)
int get_input(void)
{int nv_entry_number = 0;int got_data = 0;char *ip_data = NULL;int ip_length = 0;char tmp_buffer[(FIELD_LEN * 2) + 2];int tmp_offset = 0;char *tmp_char_ptr = NULL;int chars_processed = 0;tmp_char_ptr = (char*)M;if ( tmp_char_ptr){if(strcmp(tmp_char_ptr, "POST") == 0){tmp_char_ptr = (char*)L;if (tmp_char_ptr){ip_length = atoi(tmp_char_ptr);ip_data = malloc(ip_length + 1);if (fread(ip_data, 1, ip_length, stdin)!= ip_length){send_error("Bad read from stdin");return(0);}ip_data[ip_length] = '\0';got_data = 1;}}}tmp_char_ptr = (char*)M;if ( tmp_char_ptr){if(strcmp(tmp_char_ptr, "GET") == 0){tmp_char_ptr = (char*)S;if (tmp_char_ptr){ip_length = strlen(tmp_char_ptr);ip_data = malloc(ip_length + 1);strcpy(ip_data, (char*)S);ip_data[ip_length] = '\0';got_data = 1;}}}if (!got_data){send_error("No data received");}if (ip_length <= 0){send_error("Input length <= 0");return(0);}memset(name_val_pairs, '\0', sizeof(name_val_pairs));tmp_char_ptr = ip_data;while (chars_processed <= ip_length && nv_entry_number < NV_PAIRS){tmp_offset = 0;while (*tmp_char_ptr && *tmp_char_ptr!= '&' && tmp_offset < FIELD_LEN){tmp_buffer[tmp_offset] = *tmp_char_ptr;tmp_offset++;tmp_char_ptr++;chars_processed++;}tmp_buffer[tmp_offset] = '\0';load_nv_pair(tmp_buffer, nv_entry_number);tmp_char_ptr++;nv_entry_number++;}free(ip_data);ip_data = NULL;return(1);
}
-
功能:
-
首先,通过
M
检查请求方法。 -
如果是
POST
方法,通过L
获取内容长度,分配足够的内存给ip_data
,使用fread
从标准输入读取数据,处理读取错误。 -
如果是
GET
方法,通过S
获取查询字符串,分配内存给ip_data
,复制查询字符串,添加字符串结束符。 -
检查是否有数据,如果没有数据,调用
send_error
函数报错。 -
检查输入长度是否小于等于 0,若是则报错。
-
清空
name_val_pairs
数组。 -
遍历
ip_data
,将数据存储在tmp_buffer
中,遇到&
符号或达到FIELD_LEN
长度时,调用load_nv_pair
函数将数据存储到name_val_pairs
数组中。 -
释放
ip_data
的内存。
-
send_error(char *error_text)
void send_error(char *error_text)
{printf("Content-Type: text/html\r\n");printf("\r\n");printf("Woops:- %s\r\n",error_text);
}
-
功能:输出 HTML 头信息和错误信息,用于向用户反馈错误信息。
load_nv_pair(char *tmp_buffer, int nv_entry)
void load_nv_pair(char *tmp_buffer, int nv_entry)
{int chars_processed = 0;char *src_char_ptr = NULL;char *dest_char_ptr = NULL;src_char_ptr = tmp_buffer;dest_char_ptr = name_val_pairs[nv_entry].name;while (*src_char_ptr && *src_char_ptr!= '=' && chars_processed < FIELD_LEN){if (*src_char_ptr == '+'){*dest_char_ptr = ' ';}else{*dest_char_ptr = *src_char_ptr;}dest_char_ptr++;src_char_ptr++;chars_processed++;}if (*src_char_ptr == '='){num_pairs++;src_char_ptr++;dest_char_ptr = name_val_pairs[nv_entry].value;chars_processed = 0;while (*src_char_ptr && *src_char_ptr!= '=' && chars_processed < FIELD_LEN){if (*src_char_ptr == '+'){*dest_char_ptr = ' ';}else{*dest_char_ptr = *src_char_ptr;}dest_char_ptr++;src_char_ptr++;chars_processed++;}}unescape_url(name_val_pairs[nv_entry].name);unescape_url(name_val_pairs[nv_entry].value);
}
-
功能:
-
将
tmp_buffer
中的数据解析为名称 - 值对,将名称存储在name_val_pairs[nv_entry].name
中,将值存储在name_val_pairs[nv_entry].value
中。 -
将
+
替换为空格。 -
调用
unescape_url
函数对名称和值进行 URL 转义处理。
-
unescape_url(char *url)
void unescape_url(char *url)
{int x,y;for (x=0,y=0; url[y]; ++x,++y ){if ( (url[x] = url[y]) == '%'){url[x] = x2c(&url[y+1]);y += 2;}}url[x] = '\0';
}
-
功能:
-
遍历
url
字符串。 -
当遇到
%
时,调用x2c
函数将后面的两个字符转换为对应的 ASCII 字符。
-
x2c(char *what)
char x2c(char *what)
{register char digit;digit = (what[0] >= 'A'? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));digit *= 16;digit += (what[1] >= 'A'? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));return(digit);
}
-
功能:将十六进制表示的字符(如
%xx
)转换为对应的 ASCII 字符。
4、应用功能主程序说明
通过bmi.c程序实现。关键代码分析说明如下:
set_env(getenv("REQUEST_METHOD"),getenv("CONTENT_LENGTH"),getenv("QUERY_STRING"));
-
getenv("REQUEST_METHOD")
:该函数用于获取名为REQUEST_METHOD
的环境变量的值。在 HTTP 服务器环境中,REQUEST_METHOD
通常包含请求的方法,例如GET
、POST
、PUT
等。 -
getenv("CONTENT_LENGTH")
:该函数用于获取名为CONTENT_LENGTH
的环境变量的值。在 HTTP 请求中,如果是POST
方法,CONTENT_LENGTH
表示请求体的长度。 -
getenv("QUERY_STRING")
:该函数用于获取名为QUERY_STRING
的环境变量的值。在 HTTP 的GET
请求中,QUERY_STRING
包含了 URL 中的查询部分(即?
后面的部分)。
val_cm = get_value("cm"); val_kg = get_value("kg");
-
通过getvalue.h文件中的自定义函数get_value,可根据传入的名称查找并返回对应的字符串值。
bmi.c文件源码:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include "getvalue.h"int main(int argc, char *argv[])
{char *val_cm = NULL;char *val_kg = NULL;int cm,kg,len;float cm_f=0.0,kg_f=0.0,bmi=0.0;set_env(getenv("REQUEST_METHOD"),getenv("CONTENT_LENGTH"),getenv("QUERY_STRING")); val_cm = get_value("cm"); val_kg = get_value("kg"); cm = atoi(val_cm);kg = atoi(val_kg);cm_f = (cm + 0.0) / 100;kg_f = kg + 0.0;bmi = kg_f/(cm_f*cm_f);//计算bmi数值//下面输出信息都是HTML文件输出printf( "Content-type:text/html\n\n" ); printf("<html><body><div align=\"center\">\n");//输出调试信息printf("Debug INFO:CM=%f,KG=%f,BMI=%f \n",cm_f,kg_f,bmi);printf("<form action=\"bmi.cgi\" method=\"get\"><table> \n");printf("<tr><td rowspan=\"3\"><img src=\"../bmi.png\" hight=\"60\" width=\"120\"></td> \n");printf("<td align=\"center\" colspan=\"3\"><h2>体重指数(BMI)计算器</h2></td></tr> \n");printf("<tr><td >身高 : <input type=\"number\" name=\"cm\" min=\"1\" max=\"300\" size=\"3\"> cm </td> \n");printf("<td >体重 : <input type=\"number\" name=\"kg\" min=\"1\" max=\"500\" size=\"3\"> kg </td> \n");printf("<td align=\"center\" ><input type=submit value=\" 计 算 \" size=\"16\"> </td></tr> \n");printf("<tr><td align=\"center\" colspan=\"3\">BMI = \n");if(bmi == 0.0)printf("<input type=\"text\" name=\"ret\" value=\" \" size=\"3\" readonly></tr> \n");elseprintf("<input type=\"text\" name=\"ret\" value=\" %.1f \" size=\"3\" readonly></tr> \n",bmi); printf("</table></form></br><img src=\"../bmi_index.png\" > \n");printf("</div></body> </html> \n");return 0;
}
相关文章:

物联网网关Web服务器--CGI开发实例BMI计算
本例子通一个计算体重指数的程序来演示Web服务器CGI开发。 硬件环境:飞腾派开发板(国产E2000处理器) 软件环境:飞腾派OS(Phytium Pi OS) 硬件平台参考另一篇博客:国产化ARM平台-飞腾派开发板…...

计算机网络 (51)鉴别
前言 计算机网络鉴别是信息安全领域中的一项关键技术,主要用于验证用户或信息的真实性,以及确保信息的完整性和来源的可靠性。 一、目的与重要性 鉴别的目的是验明用户或信息的正身,对实体声称的身份进行唯一识别,以便验证其访问请…...

【Docker】搭建一个功能强大的自托管虚拟浏览器 - n.eko
前言 本教程基于群晖的NAS设备DS423的docker功能进行搭建,DSM版本为 DSM 7.2.2-72806 Update 2。 n.eko 支持多种类型浏览器在其虚拟环境中运行,本次教程使用 Chromium 浏览器镜像进行演示,支持访问内网设备和公网地址。 简介 n.eko 是…...

论文笔记(六十二)Diffusion Reward Learning Rewards via Conditional Video Diffusion
Diffusion Reward Learning Rewards via Conditional Video Diffusion 文章概括摘要1 引言2 相关工作3 前言4 方法4.1 基于扩散模型的专家视频建模4.2 条件熵作为奖励4.3 训练细节 5 实验5.1 实验设置5.2 主要结果5.3 零样本奖励泛化5.4 真实机器人评估5.5 消融研究 6 结论 文章…...

探索 Stable-Diffusion-Webui-Forge:更快的AI图像生成体验
目录 简介🌟 主要特点📥 安装步骤1. 下载2. 配置环境和安装依赖3. 模型目录说明 🚀 运行 Stable-Diffusion-Webui-Forge1. 进入项目目录2. 运行项目3. 打开页面 🎨 使用体验常见问题📝 小结 简介 Stable-Diffusion-We…...

Redis使用基础
1 redis介绍 Redis(Remote Dictionary Server ),即远程字典服务 ! 是完全开源的,遵守 BSD 协议,是一个高性能的 key-value 数据库。 使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并…...

PyCharm+RobotFramework框架实现UDS自动化测试- (四)项目实战0x10
1.环境搭建 硬件环境:CANoe、待测设备(包含UDS诊断模块) 2.pythonPyCharm环境 pip install robotframework pip install robotframework-ride pip install openpyxl pip install udsoncan pip install python-can pip install can-isotp3…...

【TCP】rfc文档
tcp协议相关rfc有哪些 TCP(传输控制协议)是一个复杂的协议,其设计和实现涉及多个RFC文档。以下是一些与TCP协议密切相关的RFC文档列表,按照时间顺序排列,涵盖了从基础定义到高级特性和优化的各个方面: 基…...

【SpringCloud】黑马微服务学习笔记
目录 1. 关于微服务 ?1.1 微服务与单体架构的区别 ?1.2 SpringCloud 技术 2. 学习前准备 ?2.1 环境搭建 ?2.2 熟悉项目 3. 正式拆分 ?3.1 拆分商品功能模块 ?3.2 拆分购物车功能模块 4. 服务调用 ?4.1 介绍 ?4.2 RustTemplate?的使用 4.3 服务治理-注册中…...

梯度提升决策树树(GBDT)公式推导
### 逻辑回归的损失函数 逻辑回归模型用于分类问题,其输出是一个概率值。对于二分类问题,逻辑回归模型的输出可以表示为: \[ P(y 1 | x) \frac{1}{1 e^{-F(x)}} \] 其中 \( F(x) \) 是一个线性组合函数,通常表示为ÿ…...

【MySQL】表的基本操作
??表的基本操作 文章目录: 表的基本操作 创建查看表 创建表 查看表结构 表的修改 表的重命名 表的添加与修改 删除表结构 总结 前言: 在数据库中,数据表是存储和组织数据的基本单位,对于数据表的操作是每个程序员需要烂熟…...

项目中使用的是 FastJSON(com.alibaba:fastjson)JSON库
从你的 pom.xml 文件中可以看到,项目明确依赖了以下 JSON 库: FastJSON: <dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.47</version> </depende…...

Flutter中PlatformView在鸿蒙中的使用
Flutter中PlatformView在鸿蒙中的使用 概述在Flutter中的处理鸿蒙端创建内嵌的鸿蒙视图创建PlatformView创建PlatformViewFactory创建plugin,注册platformview注册插件 概述 集成平台视图(后称为平台视图)允许将原生视图嵌入到 Flutter 应用…...

音频入门(一):音频基础知识与分类的基本流程
音频信号和图像信号在做分类时的基本流程类似,区别就在于预处理部分存在不同;本文简单介绍了下音频处理的方法,以及利用深度学习模型分类的基本流程。 目录 一、音频信号简介 1. 什么是音频信号 2. 音频信号长什么样 二、音频的深度学习分…...

规避路由冲突
路由冲突是指在网络中存在两个或多个路由器在进行路由选择时出现矛盾,导致网络数据包无法正确传输,影响网络的正常运行。为了规避路由冲突,可以采取以下措施: 一、合理规划IP地址 分配唯一IP:确保每个设备在网络中都有…...

SQLmap 自动注入 -02
1: 如果想获得SQL 数据库的信息,可以加入参数: -dbs sqlmap -u "http://192.168.56.133/mutillidae/index.php?pageuser-info.php&usernamexiaosheng&passwordabc&user-info-php-submit-buttonViewAccountDetails" --batch -p username -dbs…...

4.JoranConfigurator解析logbak.xml
文章目录 一、前言二、源码解析GenericXMLConfiguratorlogback.xml解析通过SaxEvent构建节点model解析model节点DefaultProcessor解析model 三、总结 一、前言 上一篇介绍了logback模块解析logback.mxl文件的入口, 我们可以手动指定logback.xml文件的位置, 也可以使用其它的名…...

React 19 新特性总结
具体详见官网: 中文:React 19 新特性 英文:React 19 新特性 核心新特性 1. Actions 解决问题:简化数据变更和状态更新流程 以前需要手动处理待定状态、错误、乐观更新和顺序请求需要维护多个状态变量(isPending, error 等) 新…...

kafka学习笔记6 ACL权限 —— 筑梦之路
在Kafka中,ACL(Access Control List)是用来控制谁可以访问Kafka资源(如主题、消费者组等)的权限机制。ACL配置基于Kafka的kafka-acls.sh工具,能够管理对资源的读取、写入等操作权限。 ACL介绍 Kafka的ACL是…...

【Java】Java抛异常到用户界面公共封装
前言 在Java中处理代码运行异常是常见的技术点之一,我们大部分会使用封装的技巧将异常进行格式化输出,方便反馈给用户界面,也是为了代码复用 看看这行代码是怎么处理异常的 CommonExceptionType.SimpleException.throwEx("用户信息不…...

基于Redis实现短信验证码登录
目录 1 基于Session实现短信验证码登录 2 配置登录拦截器 3 配置完拦截器还需将自定义拦截器添加到SpringMVC的拦截器列表中 才能生效 4 Session集群共享问题 5 基于Redis实现短信验证码登录 6 Hash 结构与 String 结构类型的比较 7 Redis替代Session需要考虑的问题 8 …...

步入响应式编程篇(二)之Reactor API
步入响应式编程篇(二)之Reactor API 前言回顾响应式编程Reactor API的使用Stream引入依赖Reactor API的使用流源头的创建 reactor api的背压模式发布者与订阅者使用的线程查看弹珠图查看形成新流的日志 前言 对于响应式编程的基于概念,以及J…...

Oracle SQL: TRANSLATE 和 REGEXP_LIKE 的知识点详细分析
目录 前言1. TRANSLATE2. REGEXP_LIKE3. 实战 前言 🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF 1. TRANSLATE TRANSLATE 用于替换字符串中指定字符集的每个字符,返回替换后的字符串 逐一映射输入字…...

RabbitMQ 在实际应用时要注意的问题
1. 幂等性保障 1.1 幂等性介绍 幂等性是数学和计算机科学中某些运算的性质,它们可以被多次应⽤,⽽不会改变初始应⽤的结果. 应⽤程序的幂等性介绍 在应⽤程序中,幂等性就是指对⼀个系统进⾏重复调⽤(相同参数),不论请求多少次,这些请求对系统的影响都是相同的效果. ⽐如数据库…...

算法日记8:StarryCoding60(单调栈)
一、题目 二、解题思路: 题意为让我们找到每个元素的左边第一个比它小的元素,若不存在则输出-1 2.1法一:暴力(0n2) 首先,我们可以想到最朴素的算法:直接暴力两层for达成目标核心代码如下&…...

大象机器人发布首款穿戴式数据采集器myController S570,助力具身智能数据收集!
myController S570 具有较高的数据采集速度和远程控制能力,大大简化了人形机器人的编程。 myController S570 是一款可移动的轻量级外骨骼,具有 14 个关节、2 个操纵杆和 2 个按钮,它提供高数据采集速度,出色的兼容性,…...

【银河麒麟高级服务器操作系统】业务访问慢网卡丢包现象分析及处理过程
了解更多银河麒麟操作系统全新产品,请点击访问 麒麟软件产品专区:product.kylinos.cn 开发者专区:developer.kylinos.cn 文档中心:document.kylinos.cn 交流论坛:forum.kylinos.cn 服务器环境以及配置 【内核版本…...

C语言之饭店外卖信息管理系统
🌟 嗨,我是LucianaiB! 🌍 总有人间一两风,填我十万八千梦。 🚀 路漫漫其修远兮,吾将上下而求索。 C语言之饭店外卖信息管理系统 目录 设计题目设计目的设计任务描述设计要求输入和输出要求验…...

记一次 .NET某数字化协同管理系统 内存暴涨分析
一:背景 1. 讲故事 高级调试训练营里的一位朋友找到我,说他们跑在linux上的.NET程序出现了内存泄露的情况,上windbg观察发现内存都是IMAGE给吃掉了,那些image都标记了 doublemapper__deleted_ 字样,问我为啥会这样&a…...

部门管理查询部门,nginx反向代理,前端如何访问到后端Tomcat 注解@RequestParam
接口开发 增删改通常是不用返回data数据,返回null 列表查询-结果封装,时间 前后端联调测试 nginx反向代理,前端如何访问到后端Tomcat服务器 删除部门...