82.管道实现cgi内存多线程查询
总体思路就是客户端写入要查询的数据到管道中,服务器端从管道读取,然后写入随机文件,再把文件名写入管道,然后客户端再读取文件
服务器端
- 设置缓冲区大写,设置管道名字,以及标识有多少个线程等
//设置缓存区大小
#define SIZE 4096
//最多有多少线程
#define MAX_CONNECT 128
//一开始有10个线程存在
int startthreadnum = ;
//管道名字
char pipename[] = "\\\\.\\Pipe\\cloudpipe";//文件路径
#define path "C:\\Program Files\\Apache Software Foundation\\Apache2.2\\cgi-bin\\kaifang.txt"
//查询结果存放的路径
char randpath[] = "";
//全局的二级指针
char ** g_pp;
//标示有多少行
int imax = ; - 创建句柄结构体
//结构体,hpipe存储管道信息,hevent用于给结构体初始化,存放连接管道的信息
typedef struct info
{
HANDLE hthread;
HANDLE hpipe;
HANDLE hevent; }PIPE_ST; //创建128个结构体
PIPE_ST pipeinst[MAX_CONNECT]; - 随机生成文件名存放查询的结果
//随机生成文件名存放查询的结果
void run()
{
time_t ts;
srand((unsigned int)time(&ts));
sprintf(randpath, "C:\\Program Files\\Apache Software Foundation\\Apache2.2\\cgi-bin\\%d.txt", rand());
} - 文件载入内存
//载入内存
void loadfromfile()
{
//分配指针数组
g_pp = (char **)malloc(sizeof(char*)*imax);
//内存清零
memset(g_pp, '\0', sizeof(char*)*imax); //以读的方式打开文件
FILE *pf = fopen(path, "r");
if (pf == NULL)
{
printf("文件打开失败");
return -;
}
else
{
for (int i = ; i < imax; i++)
{
char str[] = { };
//按行读取
fgets(str, , pf);
str[ - ] = '\0';
int strlength = strlen(str); //分配内存
g_pp[i] = malloc(sizeof(char)*(strlength + )); //拷贝到分配的内存
if (g_pp[i] != NULL)
{
strcpy(g_pp[i], str);
}
}
fclose(pf);//关闭
}
} - 查询函数
//查询
void search(char *str,char * randpath)
{
//写的模式打开
FILE *pf = fopen(randpath, "w");
if (g_pp != NULL)
{ for (int i = ; i < imax; i++)
{
if (g_pp[i] != NULL)
{
//查询
char *p = strstr(g_pp[i], str);
if (p != NULL)
{
fputs(g_pp[i], pf);//输出到文件
}
}
}
}
fclose(pf);
} - 线程函数,查询结果写入随机文件,文件名再写入管道
//线程函数
DWORD WINAPI severThread(void *lp)
{
//读取到的个数
DWORD nread = ;
//写入的个数
DWORD nwrite = ;
//用于判断IO
DWORD dwbyte = ;
//缓存区
char szbuf[SIZE] = { };
//获取当前结构体
PIPE_ST curpipe = *(PIPE_ST*)lp;
//利用event初始化一个结构体
OVERLAPPED overlap = { , , , , curpipe.hevent }; while ()
{
//数据清零
memset(szbuf, , sizeof(szbuf));
//链接管道,信息写入overlap
ConnectNamedPipe(curpipe.hpipe, &overlap);
//等待连接完成
WaitForSingleObject(curpipe.hevent, INFINITE);
//检测IO,如果IO错误则退出
if (!GetOverlappedResult(curpipe.hpipe, &overlap, &dwbyte, TRUE))
{
break;
}
//读取管道中的数据到szbuf,最多读取SIZE个
if (!ReadFile(curpipe.hpipe, szbuf, SIZE, &nread, NULL))
{
puts("read fail");
break;
} char searchstr[] = { };
//去读查询谁
sscanf(szbuf, "%s", searchstr); //路径配置
run();
//查询
search(searchstr, randpath); //清零
memset(szbuf, , sizeof(szbuf));
//把路径写入管道
sprintf(szbuf, "%s", randpath);
WriteFile(curpipe.hpipe, szbuf, strlen(szbuf), &nwrite, NULL);//写入
//断开与管道的连接
DisconnectNamedPipe(curpipe.hpipe);
}
return ;
} - 初始化结构体并创建线程
//初始化结构体并创建线程
void start()
{
for (int i = ; i < startthreadnum; i++)
{
//创建管道,如果同名,则操作同一个管道
pipeinst[i].hpipe = CreateNamedPipeA(
pipename,//管道名称
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,//管道读写属性
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,//消息模式,读模式,等待模式阻塞
,//最大个数
,//输出缓冲区大小
,//输入缓冲区大小
,//超时,无限等待
NULL);
if (pipeinst[i].hpipe == INVALID_HANDLE_VALUE)
{
printf("\n%d失败", i);
return;
}
//创建事件
pipeinst[i].hevent = CreateEventA(NULL, FALSE, FALSE, FALSE);//创建事件
//创建线程
pipeinst[i].hthread = CreateThread(NULL, , severThread, &pipeinst[i], , NULL); }
printf("sever start"); } - 释放内存
//释放内存
void end()
{
for (int i = ; i < ;i++)
{
CloseHandle(pipeinst[i].hthread);
CloseHandle(pipeinst[i].hevent);
CloseHandle(pipeinst[i].hpipe);
}
} - 主函数
//主函数
void main()
{
//载入内存
loadfromfile();
//创建线程 开始查询
start();
system("pause"); }
客户端
- 设置缓存区,以及管道名字和管道句柄
//缓存区大小
#define SIZE 4096
//管道名字
char pipename[] = "\\\\.\\Pipe\\cloudpipe";
//管道句柄
HANDLE m_pipe = NULL; - CGI编码格式转换到str中
//CGI编码格式转换到str中
char* change(char *str)
{
char *tempstr = malloc(strlen(str) + );
int x = , y = ;
char assii_1, assii_2;
while (tempstr[x])
{
if ((tempstr[x] = str[y]) == '%')
{
if (str[y + ] >= 'A')
{
assii_1 = str[y + ] - ; }
else
{
assii_1 = str[y + ] - ;
}
if (str[y + ] >= 'A')
{
assii_2 = str[y + ] - ;
}
else
{
assii_2 = str[y + ] - ;
}
tempstr[x] = assii_1 * + assii_2;
y += ;
}
x++;
y++;
}
tempstr[x] = '\0';
return tempstr;
} - 主函数
void main()
{
printf("Content-type:text/html\n\n");//换行 system("ipconfig");//服务器不稳定因素,适当中断 //获取表单信息,并对信息进行处理
char szpost[] = { };
gets(szpost);
printf("%s", szpost); char*p1 = strchr(szpost, '&');
if (p1 != NULL)
{
*p1 = '\0';
}
printf("<br>%s", szpost + );
printf("<br>%s", change(szpost + )); char *p2 = strchr(p1 + , '&');
if (p2 != NULL)
{
*p2 = '\0';
}
printf("<br>%s", p1 + );
printf("<br>%s", change(p1 + )); //打开管道
m_pipe = CreateFileA(pipename, //名称
GENERIC_WRITE | GENERIC_READ,//读写
,//共享属性,1独有
NULL,//默认安全属性
OPEN_EXISTING,//打开已经存在的
FILE_ATTRIBUTE_NORMAL,
NULL); if (m_pipe == INVALID_HANDLE_VALUE)
{
printf("失败");
return;
} int nwrite;
int nread; char winfo[] = { };
//打印数据到winfo中
sprintf(winfo, "%s", change(szpost + )); //写入管道
WriteFile(m_pipe, winfo, strlen(winfo), &nwrite, NULL);
memset(winfo, , sizeof(winfo));
//读取管道
ReadFile(m_pipe, winfo, , &nread, NULL);
;
//打开文件,并读取
FILE *pf = fopen(winfo, "r");
while (!feof(pf))
{
char ch = fgetc(pf);
if (ch=='\n')
{
puts("<br>");
}
else
{
putchar(ch);
}
}
fclose(pf); system("pause");
}
完整代码:
服务器
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<Windows.h> //设置缓存区大小
#define SIZE 4096
//最多有多少线程
#define MAX_CONNECT 128
//一开始有10个线程存在
int startthreadnum = ;
//管道名字
char pipename[] = "\\\\.\\Pipe\\cloudpipe"; //文件路径
#define path "C:\\Program Files\\Apache Software Foundation\\Apache2.2\\cgi-bin\\kaifang.txt"
//查询结果存放的路径
char randpath[] = "";
//全局的二级指针
char ** g_pp;
//标示有多少行
int imax = ; //结构体,hpipe存储管道信息,hevent用于给结构体初始化,存放连接管道的信息
typedef struct info
{
HANDLE hthread;
HANDLE hpipe;
HANDLE hevent; }PIPE_ST; //创建128个结构体
PIPE_ST pipeinst[MAX_CONNECT]; //随机生成文件名存放查询的结果
void run()
{
time_t ts;
srand((unsigned int)time(&ts));
sprintf(randpath, "C:\\Program Files\\Apache Software Foundation\\Apache2.2\\cgi-bin\\%d.txt", rand());
} //载入内存
void loadfromfile()
{
//分配指针数组
g_pp = (char **)malloc(sizeof(char*)*imax);
//内存清零
memset(g_pp, '\0', sizeof(char*)*imax); //以读的方式打开文件
FILE *pf = fopen(path, "r");
if (pf == NULL)
{
printf("文件打开失败");
return -;
}
else
{
for (int i = ; i < imax; i++)
{
char str[] = { };
//按行读取
fgets(str, , pf);
str[ - ] = '\0';
int strlength = strlen(str); //分配内存
g_pp[i] = malloc(sizeof(char)*(strlength + )); //拷贝到分配的内存
if (g_pp[i] != NULL)
{
strcpy(g_pp[i], str);
}
}
fclose(pf);//关闭
}
} //查询
void search(char *str,char * randpath)
{
//写的模式打开
FILE *pf = fopen(randpath, "w");
if (g_pp != NULL)
{ for (int i = ; i < imax; i++)
{
if (g_pp[i] != NULL)
{
//查询
char *p = strstr(g_pp[i], str);
if (p != NULL)
{
fputs(g_pp[i], pf);//输出到文件
}
}
}
}
fclose(pf);
} //线程函数
DWORD WINAPI severThread(void *lp)
{
//读取到的个数
DWORD nread = ;
//写入的个数
DWORD nwrite = ;
//用于判断IO
DWORD dwbyte = ;
//缓存区
char szbuf[SIZE] = { };
//获取当前结构体
PIPE_ST curpipe = *(PIPE_ST*)lp;
//利用event初始化一个结构体
OVERLAPPED overlap = { , , , , curpipe.hevent }; while ()
{
//数据清零
memset(szbuf, , sizeof(szbuf));
//链接管道,信息写入overlap
ConnectNamedPipe(curpipe.hpipe, &overlap);
//等待连接完成
WaitForSingleObject(curpipe.hevent, INFINITE);
//检测IO,如果IO错误则退出
if (!GetOverlappedResult(curpipe.hpipe, &overlap, &dwbyte, TRUE))
{
break;
}
//读取管道中的数据到szbuf,最多读取SIZE个
if (!ReadFile(curpipe.hpipe, szbuf, SIZE, &nread, NULL))
{
puts("read fail");
break;
} char searchstr[] = { };
//去读查询谁
sscanf(szbuf, "%s", searchstr); //路径配置
run();
//查询
search(searchstr, randpath); //清零
memset(szbuf, , sizeof(szbuf));
//把路径写入管道
sprintf(szbuf, "%s", randpath);
WriteFile(curpipe.hpipe, szbuf, strlen(szbuf), &nwrite, NULL);//写入
//断开与管道的连接
DisconnectNamedPipe(curpipe.hpipe);
}
return ;
} //初始化结构体并创建线程
void start()
{
for (int i = ; i < startthreadnum; i++)
{
//创建管道,如果同名,则操作同一个管道
pipeinst[i].hpipe = CreateNamedPipeA(
pipename,//管道名称
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,//管道读写属性
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,//消息模式,读模式,等待模式阻塞
,//最大个数
,//输出缓冲区大小
,//输入缓冲区大小
,//超时,无限等待
NULL);
if (pipeinst[i].hpipe == INVALID_HANDLE_VALUE)
{
printf("\n%d失败", i);
return;
}
//创建事件
pipeinst[i].hevent = CreateEventA(NULL, FALSE, FALSE, FALSE);//创建事件
//创建线程
pipeinst[i].hthread = CreateThread(NULL, , severThread, &pipeinst[i], , NULL); }
printf("sever start"); } //释放内存
void end()
{
for (int i = ; i < ;i++)
{
CloseHandle(pipeinst[i].hthread);
CloseHandle(pipeinst[i].hevent);
CloseHandle(pipeinst[i].hpipe);
}
} //主函数
void main()
{
//载入内存
loadfromfile();
//创建线程 开始查询
start();
system("pause"); }
客户端
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<Windows.h> //缓存区大小
#define SIZE 4096
//管道名字
char pipename[] = "\\\\.\\Pipe\\cloudpipe";
//管道句柄
HANDLE m_pipe = NULL; //CGI编码格式转换到str中
char* change(char *str)
{
char *tempstr = malloc(strlen(str) + );
int x = , y = ;
char assii_1, assii_2;
while (tempstr[x])
{
if ((tempstr[x] = str[y]) == '%')
{
if (str[y + ] >= 'A')
{
assii_1 = str[y + ] - ; }
else
{
assii_1 = str[y + ] - ;
}
if (str[y + ] >= 'A')
{
assii_2 = str[y + ] - ;
}
else
{
assii_2 = str[y + ] - ;
}
tempstr[x] = assii_1 * + assii_2;
y += ;
}
x++;
y++;
}
tempstr[x] = '\0';
return tempstr;
} void main()
{
printf("Content-type:text/html\n\n");//换行 system("ipconfig");//服务器不稳定因素,适当中断 //获取表单信息,并对信息进行处理
char szpost[] = { };
gets(szpost);
printf("%s", szpost); char*p1 = strchr(szpost, '&');
if (p1 != NULL)
{
*p1 = '\0';
}
printf("<br>%s", szpost + );
printf("<br>%s", change(szpost + )); char *p2 = strchr(p1 + , '&');
if (p2 != NULL)
{
*p2 = '\0';
}
printf("<br>%s", p1 + );
printf("<br>%s", change(p1 + )); //打开管道
m_pipe = CreateFileA(pipename, //名称
GENERIC_WRITE | GENERIC_READ,//读写
,//共享属性,1独有
NULL,//默认安全属性
OPEN_EXISTING,//打开已经存在的
FILE_ATTRIBUTE_NORMAL,
NULL); if (m_pipe == INVALID_HANDLE_VALUE)
{
printf("失败");
return;
} int nwrite;
int nread; char winfo[] = { };
//打印数据到winfo中
sprintf(winfo, "%s", change(szpost + )); //写入管道
WriteFile(m_pipe, winfo, strlen(winfo), &nwrite, NULL);
memset(winfo, , sizeof(winfo));
//读取管道
ReadFile(m_pipe, winfo, , &nread, NULL);
;
//打开文件,并读取
FILE *pf = fopen(winfo, "r");
while (!feof(pf))
{
char ch = fgetc(pf);
if (ch=='\n')
{
puts("<br>");
}
else
{
putchar(ch);
}
}
fclose(pf); system("pause");
}
82.管道实现cgi内存多线程查询的更多相关文章
- Redis 小白指南(三)- 事务、过期、消息通知、管道和优化内存空间
Redis 小白指南(三)- 事务.过期.消息通知.管道和优化内存空间 简介 <Redis 小白指南(一)- 简介.安装.GUI 和 C# 驱动介绍> 讲的是 Redis 的介绍,以及如何 ...
- Linux系统编程之命名管道与共享内存
在上一篇博客中,我们已经熟悉并使用了匿名管道,这篇博客我们将讲述进程间通信另外两种常见方式--命名管道与共享内存. 1.命名管道 管道是使用文件的方式,进行进程之间的通信.因此对于管道的操作,实际上还 ...
- CGI编程学习----查询2000W开房数据
原文:CGI编程学习----查询2000W开房数据 0x01:什么是CGI编程? CGI:Common Gateway Interface CGI代表Common Gateway Interface( ...
- 多线程查询数据,将结果存入到redis中,最后批量从redis中取数据批量插入数据库中【我】
多线程查询数据,将结果存入到redis中,最后批量从redis中取数据批量插入数据库中 package com.xxx.xx.reve.service; import java.util.ArrayL ...
- Java数据库分表与多线程查询结果汇总
今天接到一个需求:要对一个物理分表的逻辑表进行查询统计.而数据库用的是公司自己研发的产品,考虑的到公司产品的特点以及业务的需求,该逻辑表是按年月进行分表的,而非分区.我们来看一下,在按时间段进行查询统 ...
- pthread实现多线程查询(转)
导读:大多数网站的性能瓶颈不在PHP服务器上,因为它可以简单地通过横向增加服务器或CPU核数来轻松应对(对于各种云主机,增加VPS或CPU核数就更方便了,直接以备份镜像增加VPS,连操作系统.环境都不 ...
- 撸代码--类QQ聊天实现(基于linux 管道 信号 共享内存)
一:任务描写叙述 A,B两个进程通过管道通信,像曾经的互相聊天一样,然后A进程每次接收到的数据通过A1进程显示(一个新进程,用于显示A接收到的信息),A和A1间的数据传递採用共享内存,相应的有一个B1 ...
- Linux 进程间通信(管道、共享内存、消息队列、信号量)
进程通信 : 不同进程之间传播或交换信息 为什么要进程通信呢? 协同运行,项目模块化 通信原理 : 给多个进程提供一个都能访问到的缓冲区. 根据使用场景,我们能划分为以下几种通信 ...
- C实现进程间通信(管道; 共享内存,信号量)
最近学习了操作系统的并发:以下是关于进程间实现并发,通信的两个方法. 例子: 求100000个浮点数的和.要求: (1)随机生成100000个浮点数(父进程). (2)然后创建4个后代进程,分别求25 ...
随机推荐
- Gym - 100625D Destination Unknown 最短路
http://codeforces.com/gym/100625/attachments/download/3213/2013-benelux-algorithm-programming-contes ...
- 洛谷P1919 【模板】A*B Problem升级版(FFT快速傅里叶)
题目描述 给出两个n位10进制整数x和y,你需要计算x*y. 输入输出格式 输入格式: 第一行一个正整数n. 第二行描述一个位数为n的正整数x. 第三行描述一个位数为n的正整数y. 输出格式: 输出一 ...
- Python(三) 变量与运算符
一.什么是变量 变量 = [1,2] 二.变量的命名规则 字母,数字,下划线,首字母不能是数字 系统关键字 不能用在变量名中 保留关键字 区别大小写 a=1, a='1', a=(1,2), ...
- 好吧,左小波出山了——ie8兼容indexOf问题
我,还是一个不懂世事的毛头小子,第一次写博.万事开头难,没事咱慢慢来.咳,练文笔吗.我觉得写东西最锻炼逻辑思维,我是一个不善于表达的人,可能是程序员的通病,但你看看人家王小波,八九十年代的作家兼职程序 ...
- Python, Django 性能分析工具的使用
最近接手的 Apache HUE 项目性能出现了问题,线上经常出现响应时间过长或因为时间过长而无法服务等问题.老大让我准备弄个性能分析工具,便于追踪和分析平台当前的瓶颈出现在哪里. 那就搞起吧!先从代 ...
- 今日SGU 5.19
SGU 142 题意:给你一个长度为n的串(由a,b组成),让你找出一个串不是n的子串,长度最下 收获:思维题,思路在代码里 #include<bits/stdc++.h> #define ...
- springboot 前后端分离开发解决跨域访问
最近新学习了Java EE开发框架springboot,我在使用springboot前后台分离开发的过程中遇到了跨域求问题.在网上寻找答案的过程中发现网上的解决方案大多比较零散,我在这里整理一个解决方 ...
- Volitale
例1 volatile提醒编译器它后面所定义的变量随时都有可能改变.因此编译后的程序每次须要存储或读取这个变量的时候,都会直接从变量地址中读取数据. 假设没有volatile关键字.则编译器可能优化读 ...
- Android资源推荐
Intellj IDEA 安装配置 使用IntelliJ IDEA 13搭建Android集成开发环境(图文教程) Android设计指南站点 图标 App Icon Template免费的Photo ...
- 4.cocos场景和层的调用
调用关系: AppDeligate.cpp bool AppDelegate::applicationDidFinishLaunching() { // initialize director aut ...