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 ...
随机推荐
- 分享一个tom大叔的js 深入理解系列 (有助于提升)
http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html#3620172
- 二分法查找 js 算法
二分法查找算法:采用二分法查找时,数据需是排好序的.主要思想是:(设查找的数组区间为array[s, e])(1)确定该区间的中间位置m(2)将查找的值T与array[m]比较,若相等,查找成功返回此 ...
- SQL Server 2008 R2 超详细安装图文教程及问题解决(锐姿公司安装)
问题点: 1.为了sqlserver与mysql 的安全,建议数据库低权限运行.禁止远程访问 1433与 3306端口等. 2.安装提示.net 3.5没有安装 ,在server2012的添加 3. ...
- Linux下QQ的使用并手动设置QQ文件保存路径
一.背景&&目标 马化腾迟迟不肯做linux版本的QQ和微信,实在抠脚. 没有办法,要在linux上使用QQ,目前我找到最好的办法就是使用wine,然而wine这个杀千刀的又是个坑货, ...
- Yeslab 华为安全HCIE七门之-防火墙基础(12篇)
Yeslab 华为安全HCIE七门之-防火墙基础(12篇) Yeslab 全套华为安全HCIE七门之第二门防火墙基础(12篇),第一门课论坛很早就有了,可自行下载,后面的陆续分享给大家. 华为安全HC ...
- 紫书 例题 9-14 UVa 1218 (树形dp)
这道题有个初始值设成1e9, 然后这个值是要加很多次的,然后就会溢出变成负数, 然后就一直WA, 找这个bug找了一个小时--以后不能随便这样设那么大, 要考虑会不会加很多次然后溢出. 讲一下思路. ...
- 【CS Round #37 (Div. 2 only) D】Reconstruct Graph
[Link]:https://csacademy.com/contest/round-37/task/reconstruct-graph/statement/ [Description] 给你一张图; ...
- 获取个人借阅信息---图书馆client
在上一篇利用jsoup解析个人信息----图书馆client,获得个人基本信息后.便有了进一步的需求:获取当前借阅的具体信息 获取的方法还是一样的.利用jsoup解析借阅信息页面,获得所需数据,封装成 ...
- 解决QML开发中ComboBox中一个已选择项没有清除的问题
解决QML开发中ComboBox中一个已选择项没有清除的问题 近期使用QML开发一个项目.须要使用ComboBox进行显示.当进行一个操作时,须要向ComboBox加入一个元素,当进行另外一个操作时. ...
- RecyclerView实现瀑布流布局
RecyclerView本身提供了三个LayoutManager的实现 LinearLayoutManager GridLayoutManager StaggeredGridLayoutManager ...