总体思路就是客户端写入要查询的数据到管道中,服务器端从管道读取,然后写入随机文件,再把文件名写入管道,然后客户端再读取文件

服务器端


  • 设置缓冲区大写,设置管道名字,以及标识有多少个线程等

     //设置缓存区大小
    #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内存多线程查询的更多相关文章

  1. Redis 小白指南(三)- 事务、过期、消息通知、管道和优化内存空间

    Redis 小白指南(三)- 事务.过期.消息通知.管道和优化内存空间 简介 <Redis 小白指南(一)- 简介.安装.GUI 和 C# 驱动介绍> 讲的是 Redis 的介绍,以及如何 ...

  2. Linux系统编程之命名管道与共享内存

    在上一篇博客中,我们已经熟悉并使用了匿名管道,这篇博客我们将讲述进程间通信另外两种常见方式--命名管道与共享内存. 1.命名管道 管道是使用文件的方式,进行进程之间的通信.因此对于管道的操作,实际上还 ...

  3. CGI编程学习----查询2000W开房数据

    原文:CGI编程学习----查询2000W开房数据 0x01:什么是CGI编程? CGI:Common Gateway Interface CGI代表Common Gateway Interface( ...

  4. 多线程查询数据,将结果存入到redis中,最后批量从redis中取数据批量插入数据库中【我】

    多线程查询数据,将结果存入到redis中,最后批量从redis中取数据批量插入数据库中 package com.xxx.xx.reve.service; import java.util.ArrayL ...

  5. Java数据库分表与多线程查询结果汇总

    今天接到一个需求:要对一个物理分表的逻辑表进行查询统计.而数据库用的是公司自己研发的产品,考虑的到公司产品的特点以及业务的需求,该逻辑表是按年月进行分表的,而非分区.我们来看一下,在按时间段进行查询统 ...

  6. pthread实现多线程查询(转)

    导读:大多数网站的性能瓶颈不在PHP服务器上,因为它可以简单地通过横向增加服务器或CPU核数来轻松应对(对于各种云主机,增加VPS或CPU核数就更方便了,直接以备份镜像增加VPS,连操作系统.环境都不 ...

  7. 撸代码--类QQ聊天实现(基于linux 管道 信号 共享内存)

    一:任务描写叙述 A,B两个进程通过管道通信,像曾经的互相聊天一样,然后A进程每次接收到的数据通过A1进程显示(一个新进程,用于显示A接收到的信息),A和A1间的数据传递採用共享内存,相应的有一个B1 ...

  8. Linux 进程间通信(管道、共享内存、消息队列、信号量)

           进程通信 : 不同进程之间传播或交换信息    为什么要进程通信呢? 协同运行,项目模块化 通信原理 : 给多个进程提供一个都能访问到的缓冲区. 根据使用场景,我们能划分为以下几种通信 ...

  9. C实现进程间通信(管道; 共享内存,信号量)

    最近学习了操作系统的并发:以下是关于进程间实现并发,通信的两个方法. 例子: 求100000个浮点数的和.要求: (1)随机生成100000个浮点数(父进程). (2)然后创建4个后代进程,分别求25 ...

随机推荐

  1. 分享一个tom大叔的js 深入理解系列 (有助于提升)

    http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html#3620172

  2. 二分法查找 js 算法

    二分法查找算法:采用二分法查找时,数据需是排好序的.主要思想是:(设查找的数组区间为array[s, e])(1)确定该区间的中间位置m(2)将查找的值T与array[m]比较,若相等,查找成功返回此 ...

  3. SQL Server 2008 R2 超详细安装图文教程及问题解决(锐姿公司安装)

    问题点: 1.为了sqlserver与mysql 的安全,建议数据库低权限运行.禁止远程访问 1433与 3306端口等. 2.安装提示.net 3.5没有安装 ,在server2012的添加 3. ...

  4. Linux下QQ的使用并手动设置QQ文件保存路径

    一.背景&&目标 马化腾迟迟不肯做linux版本的QQ和微信,实在抠脚. 没有办法,要在linux上使用QQ,目前我找到最好的办法就是使用wine,然而wine这个杀千刀的又是个坑货, ...

  5. Yeslab 华为安全HCIE七门之-防火墙基础(12篇)

    Yeslab 华为安全HCIE七门之-防火墙基础(12篇) Yeslab 全套华为安全HCIE七门之第二门防火墙基础(12篇),第一门课论坛很早就有了,可自行下载,后面的陆续分享给大家. 华为安全HC ...

  6. 紫书 例题 9-14 UVa 1218 (树形dp)

    这道题有个初始值设成1e9, 然后这个值是要加很多次的,然后就会溢出变成负数, 然后就一直WA, 找这个bug找了一个小时--以后不能随便这样设那么大, 要考虑会不会加很多次然后溢出. 讲一下思路. ...

  7. 【CS Round #37 (Div. 2 only) D】Reconstruct Graph

    [Link]:https://csacademy.com/contest/round-37/task/reconstruct-graph/statement/ [Description] 给你一张图; ...

  8. 获取个人借阅信息---图书馆client

    在上一篇利用jsoup解析个人信息----图书馆client,获得个人基本信息后.便有了进一步的需求:获取当前借阅的具体信息 获取的方法还是一样的.利用jsoup解析借阅信息页面,获得所需数据,封装成 ...

  9. 解决QML开发中ComboBox中一个已选择项没有清除的问题

    解决QML开发中ComboBox中一个已选择项没有清除的问题 近期使用QML开发一个项目.须要使用ComboBox进行显示.当进行一个操作时,须要向ComboBox加入一个元素,当进行另外一个操作时. ...

  10. RecyclerView实现瀑布流布局

    RecyclerView本身提供了三个LayoutManager的实现 LinearLayoutManager GridLayoutManager StaggeredGridLayoutManager ...