linux网络项目——基于WebServer的工业数据采集项目

news2024/11/16 12:30:20

一、项目目标和框图

项目目标:实现通过网页控制信息采集和通过网页控制灯泡和蜂鸣器的亮灭

二、项目分析

1.服务器源码分析

  1. 初始化服务器
  2. 循环等待连接,连接后创建线程,调用线程函数msg_request,在函数中调用handler_msg函数分析请求
  3. handler_msg函数中,先查看请求协议内容,其次获取请求方法、URL、参数,判断请求方法,对need_handler赋值,确定请求资源路径,如果请求地址没有携带任何资源,则默认返回index.html文件,如果资源不存在,返回404,如果需要处理(get带参数、post)调用handle_request函数,如果不需要(get请求不带参数且资源存在),调用echo_www函数,直接返回资源
  4. handle_request函数主要获取post数据,调用parse_and_process函数处理正文内容

2. 结合Modbus部分整体流程分析

三、核心功能代码

1.采集传感器数据

        modbus采集程序和webserver共同建立共享内存,modbus读取传感器得到的数据,将数据写入共享内存中;webserver将数据从共享内存中读出;

//modbus采集传感器
void *handler_thread(void *arg)
{
    key_t key;
    int shmid;
    struct msp *p;

    //创建key值
    key = ftok("1.txt", 'x');
    if (key < 0)
    {
        perror("ftok err");
        return NULL;
    }
    printf("key: %#x\n", key);

    //创建或打开共享内存
    shmid = shmget(key, 128, IPC_CREAT | IPC_EXCL | 0666); //没有则创建共享内存,已有则返回-1

    if (shmid <= 0)
    {
        if (errno == EEXIST)                //如果已存在则直接打开共享内存
            shmid = shmget(key, 128, 0666); //直接打开共享内存,返回共享内存id
        else
        {
            perror("shmget err");
            return NULL;
        }
    }
    printf("shmid: %d\n", shmid);

    //映射共享内存到用户空间
    p = (struct msp *)shmat(shmid, NULL, 0);
    if (p == (struct msp *)-1)
    {
        perror("shmat err");
        return NULL;
    }

    //操作共享内存
    while (1)
    {

        printf("handler_thread\n");
        // uint16_t dest[10] = {};
        PACK *msg = arg;
        modbus_read_registers(msg->ctx, 0, 4, p->dest);
        printf("%d %d %d %d\n", p->dest[0], p->dest[1], p->dest[2], p->dest[3]);

        //让从线程不退出,进程状态l也就是多线程
        sleep(2);
    }
    return NULL;
}
//webserver服务器
static int handler_get(int sock, const char *input)

{

    key_t key;

    int shmid;

    struct msp *p;

    //创建key值

    key = ftok("1.txt", 'x');

    if (key < 0)

    {
        perror("ftok err");
        return -1;
    }

    printf("key: %#x\n", key);



    //创建或打开共享内存

    shmid = shmget(key, 128, IPC_CREAT | IPC_EXCL | 0666); //没有则创建共享内存,已有则返回-1

    if (shmid <= 0)

    {

        if (errno == EEXIST)                //如果已存在则直接打开共享内存

            shmid = shmget(key, 128, 0666); //直接打开共享内存,返回共享内存id

        else

        {

            perror("shmget err");

            return -1;

        }

    }

    printf("shmid: %d\n", shmid);

    //映射共享内存到用户空间

    p = (struct msp *)shmat(shmid, NULL, 0);

    if (p == (struct msp *)-1)

    {

        perror("shmat err");
        return -1;

    }

    sscanf(input, "%d X%dY%dZ%d", p->dest[0], p->dest[1], p->dest[2], p->dest[3]);

     printf("g:%d X:%dY:%dZ:%d\n", p->dest[0], p->dest[1], p->dest[2], p->dest[3]);

    char reply_buf[HTML_SIZE] = {0};

    printf("handler_get\n");

    printf("%d %d%d%d\n", p->dest[0], p->dest[1], p->dest[2], p->dest[3]);

    sprintf(reply_buf, "%d %d %d %d", p->dest[0], p->dest[1], p->dest[2], p->dest[3]);

    printf("resp = %s\n", reply_buf);

    send(sock, reply_buf, strlen(reply_buf), 0);

    return 0;

}

 2.控制灯泡和蜂鸣器

       网页发出控制命令给webserver服务器控制灯和蜂鸣器的信息,webserver和modbus采集器用相同的条件建立两个程序间的消息队列,建立通信,将控制灯泡和蜂鸣器的信息传递给modbus采集器,modbus采集器用相关信息控制灯泡和蜂鸣器的开关

//modbus采集器
void *handler_thread2(void *arg)
{

    key_t key;
    int msgid;
    key = ftok(".", 9);
    if (key < 0)
    {
        perror("ftok err");
        return NULL;
    }
    printf("key:%#x\n", key);

    //打开消息队列
    msgid = msgget(key, IPC_CREAT | IPC_EXCL | 0666);
    if (msgid <= 0)
    {
        if (errno == EEXIST)
            msgid = msgget(key, 0666);
        else
        {
            perror("msgget err");
            return NULL;
        }
    }
    printf("msgid: %d\n", msgid);

    //读取消息
    struct msgbuf m;
    while(1)
    {
    msgrcv(msgid, &m, sizeof(m) - sizeof(long), 10, 0); //20:表示读取消息的类型为20,0:代表阻塞,读取完消息才返回
    printf("%d %d\n", m.num,m.num2);
   
    PACK *msg = arg;
   

        modbus_write_bit(msg->ctx2, m.num, m.num2);
        // modbus_write_bit(msg->ctx2, 1, dest[1]);
    }

//     //让从线程不退出,进程状态l也就是多线程
    return NULL;
}
//webserver服务器
static int handler_set(int sock, const char *input)

{
    key_t key;

    int msgid;

    key = ftok(".", 9);

    if (key < 0)

    {
        perror("ftok err");
        return -1;
    }

    printf("key:%#x\n", key);


    //打开消息队列

    msgid = msgget(key, IPC_CREAT | IPC_EXCL | 0666);

    if (msgid <= 0)
    {
        if (errno == EEXIST)

            msgid = msgget(key, 0666);
        else
        {

            perror("msgget err");
            return -1;
        }
    }

    printf("msgid: %d\n", msgid);

    int number1,number2;

    //input必须是"data1=1data2=6"类似的格式,注意前端过来的字符串会有双引号

    sscanf(input, "set=%dset2=%d", &number1,&number2);

     printf("num1 = %d,num2=%d\n", number1,number2);

    char reply_buf[HTML_SIZE] = {0};

    struct msgbuf mng;

    mng.type = 10;

    mng.num = number1;

    mng.num2 =number2;

    mng.ch = 'a';

    msgsnd(msgid, &mng, sizeof(mng) - sizeof(long), 0); //0:阻塞,发完消息才返回

    printf("num = %d  num=%d\n", number1 ,number2);

    sprintf(reply_buf, "set=%dset2=%d", number1,number2);

    printf("resp = %s\n", reply_buf);

    send(sock, reply_buf, strlen(reply_buf), 0);

    return 0;

}

3.http网页显示和控制

将虚拟机的IP地址在网页中打开,然后查询传感器得到的数据和控制灯泡和蜂鸣器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>信息采集</title>
    <script>
           function get_info()
         {
            var v = document.getElementsByName("username");

            var xhr = new XMLHttpRequest();//创建对象
            var url = "";
            xhr.open("post", url, true);
            xhr.onreadystatechange = function ()
             {
                if (xhr.readyState === 4 && xhr.status === 200) 
                {
                    console.log(xhr.responseText);
                    var str1 = xhr.responseText.split("", 2);
                    

                    console.log(str1[0]);
                    console.log(str1[1]);
                    v[0].value = str1[0];
                    v[1].value = str1[1];
                }
            };
            xhr.send("g:%#x X:%#xY:%#xZ:%#x");
        }
       function sendStatus(addr,status) 
        {
            var xhr = new XMLHttpRequest();
            var url = "";
            xhr.open("post", url, true);
            data = "set=" + addr + "set2=" + status;
            console.log("req=" + data);
            if (xhr.readyState === 4 && xhr.status === 200)
             {

                var str1 = xhr.responseTest;
                console.log("resp=" + response);

            };
            xhr.send(data);

        }
         
        function set_status(obj) 
        {
            if (obj == 'ledon') 
            {
                sendStatus(0, 1);
            }
            else if (obj == 'ledoff') 
            {
                sendStatus(0, 0);
            }
            else if (obj == 'buzzeron') 
            {
                sendStatus(1, 1);
            }
            else if (obj == 'buzzeroff') 
            {
                sendStatus(1, 0);
            }
        }
        function get_info()
        {
            var v=document.getElementsByName("username");
           // v[0].value="hello";
           var xhr = new XMLHttpRequest;//创建对象
           var url="";
           xhr.open("post",url,ture);
           xhr.onreadystatechange=function()
           {
            if(xhr.readyState==4&&xhr.status==200)
            {
                console.log(xhr.responseText);
                v[0].value=xhr.responseText;
            }
           };
           xhr.send("modbus_get");
         }
    </script>
</head>
<body>
    <!--h1-h6是标题标签-->
   <h1>what 阿尔 donging 呢?</h1>
   yes,我吃饭嘞
   <br>
   <!--br表示换行-->
    NO,我 dont eat
    <div style="color:crimson;background:deepskyblue;">
    <p>
        <!--p段落标签-->
            HTML(英文Hyper Text Markup Language的缩写)中文译为“超文本标记语言”。是用来描述网页的一种语言。
            所谓超文本,因为它可以加入图片、声音、动画、多媒体等内容,不仅如此,它还可以从一个文件跳转到另一个文件,与世界各地主机的文件连接。
            HTML 不是一种编程语言,而是一种标记语言 (markup language)
            Web 浏览器的作用是读取 HTML 文档,并以网页的形式显示出它们。浏览器不会显示 HTML 标签,而是使用标签来解释页面的内容
            
            
     </p>
    </div>
    用户名:
    <!--input 表单标签,
     type类型为特殊他表示文本输入框
    value为默认值-->
    <input type="test" name="username" value="lisi">
    <input type="button"  name="flash" onclick="get_info()">
     <br>
     <!-- type类型为radio表示单选框,
        表示同样类型的单选框name 必须相同 ,
    -->
    <h1>设备控制</h1>
    <br>
    LED灯
    on:<input type="radio" name="deng" id="ledon" checked="checked" onclick="set_status(id)">
    off:<input type="radio" name="deng" id="ledoff" onclick="set_status(id)">
    <br>
    蜂鸣器
    on:<input type="radio" name="qi" id="buzzeron" checked="checked" onclick="set_status(id)">
    off:<input type="radio" name="qi" id="buzzeroff" onclick="set_status(id)">

</body>

</html>

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

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

相关文章

AI大模型探索之路-实战篇10:数据预处理的艺术:构建Agent智能数据分析平台的基础

系列篇章&#x1f4a5; AI大模型探索之路-实战篇4&#xff1a;深入DB-GPT数据应用开发框架调研 AI大模型探索之路-实战篇5&#xff1a;探索Open Interpreter开放代码解释器调研 AI大模型探索之路-实战篇6&#xff1a;掌握Function Calling的详细流程 AI大模型探索之路-实战篇7…

Web开发中,就session和cookie相比,用session比用cookie的优点有哪些?

在Web项目中&#xff0c;session和cookie都是用于存储用户数据的机制&#xff0c;但它们有不同的优缺点。使用session比使用cookie有以下几个主要优点&#xff1a; 1. 安全性更高 敏感数据保护&#xff1a;Session数据存储在服务器端&#xff0c;而不是客户端。这样&#xff…

什么叫USDT(泰达币)的前世今生!

一、引言 在数字货币的世界里&#xff0c;USDT&#xff08;Tether USDT&#xff09;以其独特的稳定机制&#xff0c;成为了连接传统金融市场与加密货币市场的桥梁。本文将带您了解USDT的诞生背景、发展历程、技术特点以及未来展望。 二、USDT的诞生背景 USDT是Tether公司推出…

QT::QNetworkReply类readAll()读取不到数据的可能原因

程序中&#xff0c;当发送请求时&#xff0c;并没有加锁&#xff0c;而是在响应函数中加了锁&#xff0c;导致可能某个请求的finished信号影响到其他请求响应数据的读取 connect(reply,&QNetworkReply::finished,this,&Display::replyFinished);参考这篇文章&#xff…

5.28.1 使用卷积神经网络检测乳腺癌

深度学习技术正在彻底改变医学图像分析领域&#xff0c;因此在本研究中&#xff0c;我们提出了卷积神经网络 (CNN) 用于乳腺肿块检测&#xff0c;以最大限度地减少手动分析的开销。CNN 架构专为特征提取阶段而设计&#xff0c;并采用了更快的 R-CNN 的区域提议网络 (RPN) 和感兴…

windows镜像虚拟机创建共享文件夹详细步骤 -- 和本地电脑传输文件

第一步&#xff1a;关闭客户机 第二步&#xff1a;右击“虚拟机名称”或菜单栏的“虚拟机”–>“设置” 网络适配器选择NAT或者其他的都可以 来到“选项”&#xff0c;启用共享文件夹&#xff0c;具体如下图&#xff1a;点击添加&#xff0c;添加主机文件夹。然后确定 第三步…

第3章 数据链路层

王道学习 考纲内容 &#xff08;一&#xff09;数据链路层的功能 &#xff08;二&#xff09;组帧 &#xff08;三&#xff09;差错控制 检错编码&#xff1b;纠错编码 &#xff08;四&#xff09;流量控制与可靠传输机制 流量控制、可靠传输与滑动窗口…

怎么藏族翻译中文在线翻译?更好地了解藏族文化

怎么藏族翻译中文在线翻译&#xff1f;着全球化的发展&#xff0c;语言交流的重要性日益凸显。藏族&#xff0c;作为中国的一个古老而神秘的民族&#xff0c;其语言对于很多人来说充满了神秘感。然而&#xff0c;在今天的数字化时代&#xff0c;我们有了更多的工具来打破语言壁…

Pytorch-Reduction Ops

文章目录 前言1.torch.argmax()2.torch.argmin()3.torch.amax()4.torch.amin()5.torch.all()6.torch.any()7.torch.max()8.torch.dist()9.torch.logsumexp()10.torch.mean()11.torch.norm()12.torch.nansum()13.torch.prod()14.torch.cumsum()15.torch.cumprod() 前言 1.torch.…

Vue 实例

一、页面效果图 二、代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><script src"../vue.js" type"text/javascript"></script><title>vue 实例</title></head><body>&l…

Jmeter 安装教程:简单易懂

随着互联网的不断发展&#xff0c;网站和应用程序的性能测试变得越来越重要。Apache JMeter 是一款广泛使用的性能测试工具&#xff0c;它强大且使用广泛&#xff0c;适用于各种性能测试需求。不论你是刚刚接触性能测试的新手&#xff0c;还是一位有经验的测试工程师&#xff0…

【ORB_SLAM系列3】—— 如何在Ubuntu18.04中使用自己的单目摄像头运行ORB_SLAM3(亲测有效,踩坑记录)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、ORB_SLAM3源码编译二、ORB_SLAM3实时单目相机测试1. 查看摄像头的话题2. 运行测试 三. 运行测试可能的报错1. 报错一(1) 问题描述(2) 原因分析(3) 解决 2. …

redis--集群节点维护

添加节点 因公司业务发展迅猛&#xff0c;现有的三主三从redis cluster架构可能无法满足现有业务的并发写入需求&#xff0c;因此公司紧急采购一台服务器192.168.7.107&#xff0c;需要将其动态添加到集群当中其不能影响业务使用和数据丢失&#xff0c;则添加过程如下: 同步之…

适合多种苛刻环境的惯性测量单元M-G370PDS

全球IMU市场d在汽车和机器人技术进步和不断增长的应用需求&#xff0c;保持着高速增长的趋势&#xff0c;其中航空航天、国防和汽车等行业对高精度、稳定和紧凑的IMU需求尤为强烈&#xff0c;这些行业对精度和可靠性的高要求直接影响了相关技术的发展方向。 爱普生惯性测量单…

【错题集-编程题】天使果冻(递推)

牛客对应题目链接&#xff1a;天使果冻 (nowcoder.com) 一、分析题目 预处理 递推 / 动态规划 f[i]&#xff1a;表示前 i 个数中的最大值。g[i]&#xff1a;表示前 i 个数中的第二大的值。 状态转移方程&#xff1a; f[i] max(f[i-1], arr[i]);arr[i] > f[i-1]&#xf…

实用新型专利申请被驳回原因

实用新型专利作为知识产权的重要组成部分&#xff0c;对推动技术创新和产业发展具有重要意义。然而&#xff0c;在申请实用新型专利的过程中&#xff0c;有时会遇到被驳回的情况。 实用新型专利被驳回的一个常见原因是技术方案不具备新颖性、创造性和实用性等专利授权条件。专利…

如何使用SSRFire自动扫描和发现SSRF漏洞

关于SSRFire SSRFire是一款针对SSRF漏洞的自动化漏洞挖掘工具&#xff0c;在该工具的帮助下&#xff0c;广大研究人员只需要给该工具提供一个目标域名和服务器信息&#xff0c;SSRFire将帮助我们自动挖掘出潜在的SSRF漏洞。除此之外&#xff0c;该工具还可以挖掘XSS以及开放重…

c语言 分而治之(施特拉森矩阵乘法)

给定两个大小分别为 nxn 的方阵 A 和 B&#xff0c;求它们的乘法矩阵。 朴素方法&#xff1a;以下是两个矩阵相乘的简单方法。 void multiply(int A[][N], int B[][N], int C[][N]) { for (int i 0; i < N; i) { for (int j 0; j < N; j) { …

IEnumerable 、 IEnumerator,yield return

自定义迭代类 》》》using System.Collections; using System.Collections; using System.Runtime.CompilerServices;namespace ConsoleApp1 {// 可迭代对象 标记此类可迭代 继承IEnumerable 类是可以迭代public class SpecificEnumerable : IEnumerable{private readonly …

【架构-19】架构风格比较

独立构件风格(Independent Components): 适用场景:需要灵活扩展和组合的复杂大数据应用 特点: 高度解耦:各组件之间高度独立,可单独开发和部署 灵活性和可扩展性:易于根据需求添加或替换组件 复杂度高:需要管理多个独立的组件及其交互 通信开销:组件间需要通过网络通信,可能会…