/***********************************************************************************
Copy right: hqyj Tech.
Author: jiaoyue
Date: 2023.07.01
Description: http请求处理
***********************************************************************************/
#include <sys/types.h>
#include <sys/socket.h>
#include "custom_handle.h"
#include <unistd.h>
#include <signal.h>
#include <semaphore.h>
#include <stdbool.h>
#define KB 1024
#define HTML_SIZE (64 * KB)
extern pid_t pid_poll;
extern bool flag;
// 普通的文本回复需要增加html头部
#define HTML_HEAD "Content-Type: text/html\r\n" \
"Connection: close\r\n"
extern char *p;
static int handle_login(int sock, const char *input)
{
char reply_buf[HTML_SIZE] = {0};
char *uname = strstr(input, "username=");
uname += strlen("username=");
char *p = strstr(input, "password");
*(p - 1) = '\0';
printf("username = %s\n", uname);
char *passwd = p + strlen("password=");
printf("passwd = %s\n", passwd);
if (strcmp(uname, "admin") == 0 && strcmp(passwd, "admin") == 0)
{
sprintf(reply_buf, "<script>localStorage.setItem('usr_user_name', '%s');</script>", uname);
strcat(reply_buf, "<script>window.location.href = '/index.html';</script>");
send(sock, reply_buf, strlen(reply_buf), 0);
}
else
{
printf("web login failed\n");
//"用户名或密码错误"提示,chrome浏览器直接输送utf-8字符流乱码,没有找到太好解决方案,先过渡
char out[128] = {0xd3, 0xc3, 0xbb, 0xa7, 0xc3, 0xfb, 0xbb, 0xf2, 0xc3, 0xdc, 0xc2, 0xeb, 0xb4, 0xed, 0xce, 0xf3};
sprintf(reply_buf, "<script charset='gb2312'>alert('%s');</script>", out);
strcat(reply_buf, "<script>window.location.href = '/login.html';</script>");
send(sock, reply_buf, strlen(reply_buf), 0);
}
return 0;
}
static int handle_add(int sock, const char *input)
{
int number1, number2;
// input必须是"data1=1data2=6"类似的格式,注意前端过来的字符串会有双引号
sscanf(input, "\"data1=%ddata2=%d\"", &number1, &number2);
printf("num1 = %d\n", number1);
printf("num1 = %d\n", number2);
char reply_buf[HTML_SIZE] = {0};
printf("num = %d\n", number1 + number2);
sprintf(reply_buf, "%d", number1 + number2);
printf("resp = %s\n", reply_buf);
send(sock, reply_buf, strlen(reply_buf), 0);
return 0;
}
static int handle_regDAQ(int sock, const char *input)
{
flag = false;
int data_reg[4] = {};
char reply_buf[HTML_SIZE] = "";
kill(pid_poll, SIGUSR1);
printf("85\n");
while (1)
{
if (flag)
{
printf("%s\n", p);
printf("flag:%d\n", flag);
sscanf(p, "Light Sensor:%d ; Accelerometer x:%d y:%d z:%d\n", &data_reg[0], &data_reg[1], &data_reg[2], &data_reg[3]);
sprintf(reply_buf, "%d%d%d%d", data_reg[0], data_reg[1], data_reg[2], data_reg[3]);
}
break;
}
printf("resp = %s\n", reply_buf);
send(sock, reply_buf, sizeof(reply_buf), 0);
return 0;
}
static int handle_CTRL(int sock, const char *input)
{
int regno = 0, SRB = 0;
char reply_buf[HTML_SIZE] = "";
sscanf(input, "registerno:%dSet/Reset Operations:%d", ®no, &SRB);
printf("regno = %d SRB = %d", regno, SRB);
printf("%s\n", p);
if (regno == 0)
{
if (SRB == 0)
printf("LED Lighting Deactivated\n");
else if (SRB == 1)
printf("LED Lighting Activated\n");
}
else if (regno == 1)
{
if (SRB == 0)
printf("Buzzer Disengaged\n");
else if (SRB == 1)
printf("Buzzer Engaged\n");
}
sprintf(p, "ctrl: %d %d", regno, SRB);
// kill(getpid(),SIGUSR1);
send(sock, reply_buf, sizeof(reply_buf), 0);
return 0;
}
/**
* @brief 处理自定义请求,在这里添加进程通信
* @param input
* @return
*/
int parse_and_process(int sock, const char *query_string, const char *input)
{
// query_string不一定能用的到
// 先处理登录操作
if (strstr(input, "username=") && strstr(input, "password="))
{
return handle_login(sock, input);
}
// 处理求和请求
else if (strstr(input, "data1=") && strstr(input, "data2="))
{
return handle_add(sock, input);
}
else if (strstr(input, "registers data acquisition"))
{
return handle_regDAQ(sock, input);
}
else if (strstr(input, "registerno:") && strstr(input, "Set/Reset Operations:"))
{
return handle_CTRL(sock, input);
}
else // 剩下的都是json请求,这个和协议有关了
{
// 构建要回复的JSON数据
const char *json_response = "{\"message\": \"Hello, client!\"}";
// 发送HTTP响应给客户端
send(sock, json_response, strlen(json_response), 0);
}
return 0;
}
// 读光线传感器 -> 一个保持传感器、加速度传感器(x / y / z) -> 三个保持寄存器
// 控制led灯 -> 一个线圈传感器、蜂鸣器 -> 一个线圈传感器
/*
Holding Registers -> HR
Coil Registers -> CR
LED Lighting -> LED
Buzzer -> BZ
Light Sensor -> LS
Accelerometer -> ACC
Data Acquisition -> DAQ
Control -> CTRL
*/
#include <stdio.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <modbus.h>
#include <pthread.h>
#include <time.h>
#include <string.h>
#include <sys/types.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define N 32
uint16_t data_recv[N] = {};
int num_regs = 0, addr_start = 0;
pthread_t thread_ctrl, thread_acq;
modbus_t *ctx = NULL;
char *p = NULL;
pid_t pid_self = 0, pid_webserver = 0;
// sem_t sign_acq, sign_ctrl;
void *DAQ_HR(void *arg)
{
while (1)
{
// sem_wait(&sign_acq);
modbus_read_registers(ctx, 0, 4, data_recv);
sleep(1);
// printf("Light Sensor:%d ; Accelerometer x:%d y:%d z:%d\n", data_recv[0], data_recv[1], data_recv[2], data_recv[3]);
// sem_post(&sign_ctrl);
}
pthread_exit(NULL);
}
void handle_daq(int sig)
{
if (sig == SIGUSR1)
{
sprintf(p, "Light Sensor:%d ; Accelerometer x:%d y:%d z:%d\n", data_recv[0], data_recv[1], data_recv[2], data_recv[3]);
kill(pid_webserver, SIGUSR2);
}
}
void *CTRL_CR(void *arg)
{
int dev_flag = 0, opt_flag = 0;
while (1)
{
// sem_wait(&sign_ctrl);
if (!strncmp(p, "ctrl", 4))
{
printf("%s\n", p);
sscanf(p, "ctrl: %d %d", &dev_flag, &opt_flag);
modbus_write_bit(ctx, dev_flag, opt_flag);
if (dev_flag == 0)
{
if (opt_flag == 0)
printf("LED Lighting Deactivated\n");
else if (opt_flag == 1)
printf("LED Lighting Activated\n");
}
else if (dev_flag == 1)
{
if (opt_flag == 0)
printf("Buzzer Disengaged\n");
else if (opt_flag == 1)
printf("Buzzer Engaged\n");
}
memset(p, 0, 64);
}
}
pthread_exit(NULL);
}
int main(int argc, char const *argv[])
{
// if (sem_init(&sign_ctrl, 0, 0) || sem_init(&sign_acq, 0, 1))
// {
// perror("sem_init err");
// return -1;
// }
if (argc != 3)
{
printf("format:%s <ip> <slave id>\n", argv[0]);
return -1;
}
key_t key1 = ftok("../key.c", 'a');
if (key1 < 0) // failure -> -1
{
perror("ftok err");
return -1;
}
printf("ftok success\n");
int shmid = shmget(key1, 64, IPC_CREAT | IPC_EXCL | 0777);
if (shmid < 0)
{
if (errno == EEXIST)
shmid = shmget(key1, 64, 0777);
else
{
perror("shmget err");
return -1;
}
}
printf("shmget success\n");
p = (char *)shmat(shmid, NULL, 0);
if (p == (void *)-1)
{
perror("shmat err");
return -1;
}
printf("shmat success\n");
ctx = modbus_new_tcp(argv[1], 502);
if (ctx == NULL)
{
perror("modbus_new_tcp err");
return -1;
}
modbus_set_slave(ctx, atoi(argv[2]));
if (modbus_connect(ctx) < 0)
{
perror("modbus_set_slave err");
return -1;
}
pid_t pid_self = getpid();
while (1)
{
if (strstr(p, "pid_webserver"))
{
sscanf(p, "pid_webserver:%d", &pid_webserver);
memset(p, 0, 64);
sprintf(p, "pid_poll:%d", pid_self);
break;
}
}
printf("pid_self = %d pid_webserver = %d\n", pid_self, pid_webserver);
signal(SIGUSR1, handle_daq);
signal(SIGUSR2, SIG_IGN);
pthread_create(&thread_ctrl, NULL, CTRL_CR, NULL);
pthread_create(&thread_acq, NULL, DAQ_HR, NULL);
// sem_destroy(&sign_ctrl);
// sem_destroy(&sign_acq);
pthread_join(thread_acq, NULL);
pthread_join(thread_ctrl, NULL);
modbus_close(ctx);
modbus_free(ctx);
shmdt(p);
shmctl(shmid, IPC_RMID, NULL);
return 0;
}#include "thttpd.h"
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <signal.h>
#include <semaphore.h>
#include <stdbool.h>
char *p = NULL;
pid_t pid_self = 0, pid_poll = 0;
bool flag;
static void *msg_request(void *arg)
{
// 这里客户端描述符通过参数传进来了
int sock = (int)arg;
// 一般情况下,线程终止后,其终止状态一直保留到其它线程调用pthread_join获取它的状态为止。
// 但是线程也可以被置为detach状态,这样的线程一旦终止就立刻回收它占用的所有资源,而不保留终止状态。
pthread_detach(pthread_self());
// handler_msg作为所有的请求处理入口
return (void *)handler_msg(sock);
}
void handler_get(int sig)
{
if (sig == SIGUSR2)
flag = true;
}
int main(int argc, char *argv[])
{
// 如果不传递端口,那么使用默认端口80
int port = 80;
if (argc > 1)
{
port = atoi(argv[1]);
}
key_t key1 = ftok("../key.c", 'a');
if (key1 < 0) // failure -> -1
{
perror("ftok err");
return -1;
}
printf("ftok success\n");
int shmid = shmget(key1, 64, IPC_CREAT | IPC_EXCL | 0777);
if (shmid < 0)
{
if (errno == EEXIST)
shmid = shmget(key1, 64, 0777);
else
{
perror("shmget err");
return -1;
}
}
printf("shmget success\n");
p = (char *)shmat(shmid, NULL, 0);
if (p == (void *)-1)
{
perror("shmat err");
return -1;
}
printf("shmat success\n");
// 初始化服务器
int lis_sock = init_server(port);
pid_t pid_self = getpid();
sprintf(p, "pid_webserver:%d", pid_self);
while (1)
{
if (strstr(p, "pid_poll"))
{
sscanf(p, "pid_poll:%d", &pid_poll);
memset(p, 0, 64);
break;
}
}
printf("pid_self = %d pid_poll = %d\n", pid_self, pid_poll);
signal(SIGUSR2, handler_get);
signal(SIGUSR1, SIG_IGN);
while (1)
{
struct sockaddr_in peer;
socklen_t len = sizeof(peer);
int sock = accept(lis_sock, (struct sockaddr *)&peer, &len);
if (sock < 0)
{
perror("accept failed");
continue;
}
// 每次接收一个链接后,会自动创建一个线程,这实际上就是线程服务器模型的应用
pthread_t tid;
if (pthread_create(&tid, NULL, msg_request, (void *)sock) > 0)
{
perror("pthread_create failed");
close(sock);
}
}
return 0;
}
为什么当发送SIGUSR2信号后,flag的值不变
最新发布