一、项目目标和框图
项目目标:实现通过网页控制信息采集和通过网页控制灯泡和蜂鸣器的亮灭
二、项目分析
1.服务器源码分析
- 初始化服务器
- 循环等待连接,连接后创建线程,调用线程函数msg_request,在函数中调用handler_msg函数分析请求
- 在handler_msg函数中,先查看请求协议内容,其次获取请求方法、URL、参数,判断请求方法,对need_handler赋值,确定请求资源路径,如果请求地址没有携带任何资源,则默认返回index.html文件,如果资源不存在,返回404,如果需要处理(get带参数、post)调用handle_request函数,如果不需要(get请求不带参数且资源存在),调用echo_www函数,直接返回资源
- 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地址在网页中打开,然后查询传感器得到的数据和控制灯泡和蜂鸣器
信息采集 what 阿尔 donging 呢?
yes,我吃饭嘞
NO,我 dont eatHTML(英文Hyper Text Markup Language的缩写)中文译为“超文本标记语言”。是用来描述网页的一种语言。 所谓超文本,因为它可以加入图片、声音、动画、多媒体等内容,不仅如此,它还可以从一个文件跳转到另一个文件,与世界各地主机的文件连接。 HTML 不是一种编程语言,而是一种标记语言 (markup language) Web 浏览器的作用是读取 HTML 文档,并以网页的形式显示出它们。浏览器不会显示 HTML 标签,而是使用标签来解释页面的内容
用户名:
设备控制
LED灯 on: off:
蜂鸣器 on: off:
还没有评论,来说两句吧...