基于Webserver的工业数据采集控制

http协议

  1. http简介

HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于Web Browser(浏览器)到Web Server(服务器)进行数据交互的传输协议。

HTTP是应用层协议

HTTP是一个基于TCP通信协议传输来传递数据(HTML 文件, 图片文件, 查询结果等)

HTTP协议工作于B/S架构上,浏览器作为HTTP客户端通过URL主动向HTTP服务端即WEB服务器发送所有请求,Web服务器根据接收到的请求后,向客户端发送响应信息。

HTTP默认端口号为80,但是你也可以改为8080或者其他端口

  1. http特点

HTTP是无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。

(需要注意一点:HTTP协议本身是无连接的,即每个请求和响应都是独立的。但是http想要与长连接和短连接是基于TCP协议的连接管理方式,用于优化HTTP请求和响应的传输效率。长连接是指在一个TCP连接上可以发送多个HTTP请求和响应,而不需要每次请求都建立和关闭一个新的TCP连接。短连接是指每个HTTP请求和响应都使用一个新的TCP连接。)

HTTP是媒体独立:这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。客户端以及服务器指定使用适合的MIME-type内容类型。

HTTP是无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

  1. 协议格式

1)请求格式

HTTP是什么?_哔哩哔哩_bilibili

发送一个HTTP请求到服务器的请求消息包括以下格式:请求行、请求头部、空行和请求数据四个部分组成,下图给出了请求报文的一般格式。

协议版本:http1.0  http1.1

url:地址 域名

http协议中共定义了八种数据的请求方法。分别是: OPTIONS、HEAD、GET、POST、PUT、DELETE、TRACE、CONNECT;我们在实际应用中常用的也就是 get 和 post,其他请求方式也都可以通过这两种方式间接的来实现。

GET方法和POST方法的区别?

Post(处理数据,处理完后返回给服务器,复杂一点的)

GET通常用来从服务器上获得数据,而非修改信息;POST用来向服务器传递数据。

1、请求数据时带参数时;GET请求的数据会附加在URL之后,以?分割URL和传输数据,多个参数用&连接。POST请求会把请求的数据放置在HTTP请求包的包体中。

因此,GET请求的数据会暴露在地址栏中,而POST请求则不会。

2、 传输数据的大小;在HTTP规范中,没有对URL的长度和传输的数据大小进行限制。但是在实际开发过程中,对于GET,特定的浏览器和服务器对URL的长度有限制。因此,在使用GET请求时,传输数据会受到URL长度的限制。对于POST,由于不是URL传值,理论上是不会受限制的,但是实际上各个服务器会规定对POST提交数据大小进行限制,Apache、IIS都有各自的配置。

3、GET请求返回的内容可以被浏览器缓存起来。而每次提交的POST,浏览器在你按 下F5的时候会跳出确认框,浏览器不会缓存POST请求返回的内容

4、GET对数据进行查询,POST主要对数据进行增删改!简单说,GET是只读,POST是写

5、对于参数的数据类型,get只接受ASCII字符,而post没有限制。

请求头

也被称作消息报头,请求头是由一些键值对组成,每行一对,关键字和值用英文冒号“:”分隔。允许客户端向服务器发送一些附加信息或者客户端自身的信息,典型的请求头如下:

Accept:作用:描述客户端希望接收的 响应body 数据类型;示例:Accept:text/html

Accept-Charset:作用:浏览器可以接受的字符编码集;示例:Accept-Charset:utf-8

Accept-Language:作用:浏览器可接受的语言;示例:Accept-Language:en

Connection:作用:表示是否需要持久连接,注意HTTP1.1默认进行持久连接;示例:Connection:close

Content-Length:作用:请求的内容长度:示例:Content-Length:348

Content-Type:作用:描述客户端发送的 body 数据类型

 空行:

最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头。

请求体:

请求数据:请求数据不在GET方法中使用,而是在POST方法中使用。POST方法适用于需要客户填写表单的场合。与请求数据相关的最常使用的请求头是Content-Type和Content-Length。

2)响应格式

HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文

状态行:由三部分组成,HTTP协议的版本号、状态码、以及对状态码的文本描述。例如:HTTP/1.1 (协议版本)200 (状态码)OK (CRLF) 。(200表示请求已经成功)

常见状态码:

  • 200 OK:请求成功,服务器成功处理了请求并返回所请求的资源。
  • 301 Moved Permanently:请求的资源已永久移动到新的URL,客户端应更新其链接。
  • 302 Found:请求的资源暂时移动到新的URL,客户端应继续使用原始URL。
  • 400 Bad Request:服务器无法理解请求的语法,通常是由于客户端发送的请求不正确导致的。
  • 401 Unauthorized:请求要求身份验证,客户端需要提供有效的身份凭证。
  • 403 Forbidden:服务器拒绝请求,客户端没有访问所请求资源的权限。
  • 404 Not Found:请求的资源不存在,服务器无法找到所请求的资源。
  • 500 Internal Server Error:服务器内部错误,无法完成请求的处理。
  • 503 Service Unavailable:服务器当前无法处理请求,通常是由于服务器过载或维护导致的。

一个小例子:虚拟机端打开该服务器,windows端连接服务器,ip:port

ip:虚拟机ip :英文模式冒号 port:虚拟机端服务器设置的端口

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
#define PORT 8080
#define BUFFER_SIZE 1024
void handle_request(int client_socket)
{char buffer[BUFFER_SIZE];char response[] = "HTTP/1.1 200 OK\nContent-Type: text/html\n\n<html><body><h1>Hello, World!</h1></body></html>";// 从客户端读取请求ssize_t bytes_read = read(client_socket, buffer, BUFFER_SIZE - 1);if (bytes_read == -1){perror("读取请求失败");return;}buffer[bytes_read] = '\0';// 打印请求内容printf("收到请求:\n%s\n", buffer);// 发送响应给客户端ssize_t bytes_written = write(client_socket, response, strlen(response));if (bytes_written == -1){perror("发送响应失败");}
}
int main()
{int server_socket, client_socket;struct sockaddr_in server_address, client_address;socklen_t client_address_len;// 创建套接字if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1){perror("创建套接字失败");exit(1);}// 设置地址重用,服务器端意外退出,允许再次连接该地址端口int reuse = 1;if (setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1){perror("设置地址重用失败");exit(1);}// 绑定地址server_address.sin_family = AF_INET;server_address.sin_port = htons(PORT);server_address.sin_addr.s_addr = htonl(INADDR_ANY);if (bind(server_socket, (struct sockaddr *)&server_address, sizeof(server_address)) == -1){perror("绑定地址失败");exit(1);}// 启动监听if (listen(server_socket, 10) == -1){perror("启动监听失败");exit(1);}printf("服务器已启动,监听端口 %d\n", PORT);// 接受连接并处理请求while (1){client_address_len = sizeof(client_address);if ((client_socket = accept(server_socket, (struct sockaddr *)&client_address, &client_address_len)) == -1){perror("接受连接失败");continue;}printf("接受新连接\n");// 处理请求handle_request(client_socket);// 关闭客户端套接字close(client_socket);printf("连接已关闭\n");}// 关闭服务器套接字close(server_socket);return 0;
}

函数追踪:ctrl+鼠标点击

函数返回追踪:ctrl + alt + -

webserver

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>#define PORT 8080
#define BUFFER_SIZE 1024void handle_request(int client_socket) {char buffer[BUFFER_SIZE];char response[] = "HTTP/1.1 200 OK\nContent-Type: text/html\n\n<html><body><h1>Hello, World!</h1></body></html>";// 从客户端读取请求ssize_t bytes_read = read(client_socket, buffer, BUFFER_SIZE - 1);if (bytes_read == -1) {perror("读取请求失败");return;}buffer[bytes_read] = '\0';// 打印请求内容printf("收到请求:\n%s\n", buffer);// 发送响应给客户端ssize_t bytes_written = write(client_socket, response, strlen(response));if (bytes_written == -1) {perror("发送响应失败");}
}int main() {int server_socket, client_socket;struct sockaddr_in server_address, client_address;socklen_t client_address_len;// 创建套接字if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {perror("创建套接字失败");exit(1);}// 设置地址重用int reuse = 1;if (setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) {perror("设置地址重用失败");exit(1);}// 绑定地址server_address.sin_family = AF_INET;server_address.sin_port = htons(PORT);server_address.sin_addr.s_addr = htonl(INADDR_ANY);if (bind(server_socket, (struct sockaddr *)&server_address, sizeof(server_address)) == -1) {perror("绑定地址失败");exit(1);}// 启动监听if (listen(server_socket, 10) == -1) {perror("启动监听失败");exit(1);}printf("服务器已启动,监听端口 %d\n", PORT);// 接受连接并处理请求while (1) {client_address_len = sizeof(client_address);if ((client_socket = accept(server_socket, (struct sockaddr *)&client_address, &client_address_len)) == -1) {perror("接受连接失败");continue;}printf("接受新连接\n");// 处理请求handle_request(client_socket);// 关闭客户端套接字close(client_socket);printf("连接已关闭\n");}// 关闭服务器套接字close(server_socket);return 0;
}

1、服务器源码分析

  1. 初始化服务器
  2. 循环等待连接,创建线程,调用线程函数msg_request,并且在该函数中继续调用handler_msg;
  3. 首先获取请求,其次获取请求方法、url、参数,判断方法是什么并且对need_handler赋值,确定请求资源路径,如果请求的地址没有携带任何资源,默认返回index.html,如果请求的地址不存在,则返回404.html,如果需要处理(post请求和get请求带参数),调用handle_request,如果不需要,echo_www,直接返回资源
  4. handle_request,主要获取破石头请求的数据,调用parse_and_process函数来处理数据

2、postman

结合post.html网页部分的内容,做测试

注意发送正文内容需要加“”,因为网页发送的数据是字符串

通过postman模拟浏览器,实现Modbus Slave端数据采集和设备控制

注意:

1. 存在共享内存和消息队列数据收发问题时。

解决方案:

1) 在代码中加打印语句,确保两个进程用的是同一个id

2) 由于程序是强制结束,再下次运行代码时,将消息队列删除一下

查看和删除共享内存和消息队列:

ipcs  -m  :查看共享内存

ipcrm  -m  shmid:删除共享内存

ipcs -q:查看消息队列

ipcrm  -q  semid:删除消息队列

2. key值的创建路径指定/目录下的某个新建文件

3. 多使用打印语句,排查错误位置

任务:

通过postman模拟浏览器,实现Modbus Slave端数据采集和设备控制

注意:

1. 存在共享内存和消息队列数据收发问题时。

解决方案:

1) 在代码中加打印语句,确保两个进程用的是同一个id

2) 由于程序是强制结束,再下次运行代码时,将消息队列删除一下

查看和删除共享内存和消息队列:

ipcs  -m  :查看共享内存

ipcrm  -m  shmid:删除共享内存

ipcs -q:查看消息队列

ipcrm  -q  semid:删除消息队列

2. key值的创建路径指定/目录下的某个新建文件

3. 多使用打印语句,排查错误位置

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

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

相关文章

蓝桥杯每日一题2023.11.28

题目描述 三羊献瑞 - 蓝桥云课 (lanqiao.cn) 题目分析 本题首先进行观察可以确定 1.“三”为 1 &#xff08;十进制数字要进位进一位&#xff09; 2.“祥”一定不为 0 &#xff08;有前导0就不能算为 4 位数&#xff09; 使用搜索时将其特判 #include<bits/stdc.h> …

【RLChina2023】CCF 苏州 记录

目录 RLChina介绍主旨报告专题报告智能体学习理论(专题一)智能体决策与规划(专题二)智能体框架、体系结构与训练系统(专题六)基于大语言模型的具身智能体与机器人研究 (专题八)教学报告——强化学习入门特别论坛——智能体和多智能体艺术的探索会议照片RLChina介绍 RLC…

【华为OD题库-040】计算最接近的数-java

题目 给定一个数组X和正整数K&#xff0c;请找出使表达式X[i]-x[i1]…-X[ik-1]&#xff0c;结果最接近于数组中位数的下标i&#xff0c;如果有多个满足条件&#xff0c;请返回最大的i。 其中&#xff0c;数组中位数:长度为N的数组&#xff0c;按照元素的值大小升序排列后&#…

「阿里巴巴」裁撤量子实验室!

据内部消息&#xff0c;阿里巴巴达摩院由于预算及盈利等原因&#xff0c;已经撤裁旗下量子实验室。此次&#xff0c;共计裁减30余人。 达摩院官网已撤下量子实验室的相关介绍页面。上图&#xff1a;早先关于量子实验室的相关介绍&#xff1b;下图&#xff1a;现在达摩院官网“实…

Linux 局域网传输工具LANDrop安装

Linux 局域网传输工具LANDrop安装 &#x1f959;下载&#x1f32d;解压&#x1f96a;运行 &#x1f959;下载 官网下载 或网盘 &#x1f32d;解压 使用以下命令解压获得squashfs-root文件夹 ./LANDrop-latest-linux.AppImage --appimage-extract&#x1f96a;运行 进入squ…

flutter 文本不随系统设置而改变大小[最全的整理]

文本不随系统设置而改变大小[三] 前言方案十三&#xff1a;使用Flexible方案十四&#xff1a;使用MediaQueryData的textScaleFactor属性方案十五&#xff1a;使用FractionallySizedBox方案十六&#xff1a;使用自定义文本样式方案十七&#xff1a;使用自定义绘制&#xff08;Cu…

Doris_Doris导入常见问题

Doris数据导入错误 &#xff1a;the length of input is too larger than schema 可能原因&#xff1a;varchar长度设置过短 Doris表字段乱序 导入palo表中的csv本身无schema信息&#xff0c;csv与palo表字段顺序必须一致&#xff0c;否则会错乱 Doris数据文件中字段比表字段…

探秘:性能测试中最常见的陷阱与解决方案!

概述一下性能测试流程&#xff1f; 1.分析性能需求。挑选用户使用最频繁的场景来测试。确定性能指标&#xff0c;比如&#xff1a;事务通过率为100%&#xff0c;TOP99%是5秒&#xff0c;最大并发用户为1000人&#xff0c;CPU和内存的使用率在70%以下2.制定性能测试计划&#x…

如何解决中小制造业企业信息化难题?

中小企的信息化&#xff0c;难&#xff01; 一、中小制造业企业信息化困难的原因主要有以下几点&#xff1a; 资金限制&#xff1a;中小制造业企业相对于大型企业来说资金有限&#xff0c;无法投入大量资金进行信息化建设。技术水平不足&#xff1a;中小制造业企业缺乏专业的…

C语言文件操作 | 文件分类、文件打开与关闭、文件的读写、文件状态、文件删除与重命名、文件缓冲区

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

Leetcode—828.统计子串中的唯一字符【困难】

2023每日刷题&#xff08;四十一&#xff09; Leetcode—828.统计子串中的唯一字符 算法思想 枚举所有种类字母在s中出现的位置&#xff0c;分别统计只包含这个字母不包含该类字母中其他字母的子串个数 实现代码 int uniqueLetterString(char* s) {int len strlen(s);cha…

四川天蝶电子商务有限公司真实可靠吗?

随着数字经济的不断发展&#xff0c;抖音电商服务日益成为企业拓展销售渠道、提升品牌影响力的关键一环。在这样的大背景下&#xff0c;四川天蝶电子商务有限公司凭借其专业的服务能力和创新的技术手段&#xff0c;迅速崛起为抖音电商服务领域的领军企业。 四川天蝶电子商务有限…

【解决方案】基于边缘计算技术的安科瑞综合管廊能效管理平台

平台背景 综合管廊一般是建于城市地下用于容纳两类及以上城市工程管线的构筑物及附属设施&#xff0c;将电力、自来水、热力、煤气、电信、网络等市政公用管线根据规划要求集中敷设在同一个构建物内&#xff0c;实施统一设计、施工、管理的市政公用隧道空间&#xff0c;并且还…

NAS层协议学习(三)

消息结构 每个NAS消息包含一个协议鉴别符和一个消息标识。协议鉴别符是一个 4 位值&#xff0c;指示正在使用的协议&#xff0c;即对于 EPS NAS 消息是 EMM 或 ESM。消息标识指示发送的特定消息。 EMM 消息还包含一个安全标头&#xff0c;指示消息是否受到完整性保护和/或加密…

DS图—图的最短路径/Dijkstra算法【数据结构】

DS图—图的最短路径/Dijkstra算法【数据结构】 题目描述 给出一个图的邻接矩阵&#xff0c;输入顶点v&#xff0c;用迪杰斯特拉算法求顶点v到其它顶点的最短路径。 输入 第一行输入t&#xff0c;表示有t个测试实例 第二行输入顶点数n和n个顶点信息 第三行起&#xff0c;每行…

【链接MySQL】教你用VBA链接MySQL数据库

hi&#xff0c;大家好呀&#xff01; 之前呢&#xff0c;给大家分享过一个自制链接表管理器的文章&#xff0c;文章中有链接SQL Server数据库的代码&#xff0c;大家对这一段代码比较有兴趣&#xff0c;既然大家有兴趣&#xff0c;那我们今天就来讲一下链接数据库的代码。 这…

抽象工厂模式-C语言实现

说明&#xff1a; 均由 chatgpt生成&#xff0c;实例可以看出无法运行&#xff0c;仅供参考~ 抽象工厂模式&#xff1a; 代码实现&#xff1a; #include <stdio.h>// 定义抽象产品接口 typedef struct {void (*operation)(); } AbstractProductA;typedef struct {voi…

智慧工地管理系统加快推进工程建设项目全生命周期数字化

智慧工地管系统是一种利用人工智能和物联网技术来监测和管理建筑工地的系统。它可以通过感知设备、数据处理和分析、智能控制等技术手段&#xff0c;实现对工地施工、设备状态、人员安全等方面的实时监控和管理。 智慧工地以物联网、移动互联网技术为基础&#xff0c;充分应用大…

Go 中切片(Slice)的长度与容量

切片长度与容量在 Go 中很常见。切片长度是切片中可用元素的数量&#xff0c;而切片容量是从切片中第一个元素开始计算的底层数组中的元素数量。 Go 中的开发者经常混淆切片长度和容量&#xff0c;或者对它们不够了解。理解这两个概念对于高效处理切片的核心操作&#xff0c;比…

“AI+量子模拟”突破!英伟达与美国量子技术公司SandboxAQ合作

&#xff08;图片来源&#xff1a;网络&#xff09; 11月20日&#xff0c;美国量子技术公司SandboxAQ在美国加利福尼亚州帕洛阿尔托宣布与美国人工智能计算公司英伟达&#xff08;NVIDIA&#xff09;联手&#xff0c;双方将通过人工智能和量子模拟技术助力药物发现、电池设计、…