82.管道实现cgi内存多线程查询

Posted 喵小喵~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了82.管道实现cgi内存多线程查询相关的知识,希望对你有一定的参考价值。

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

 

服务器端


 

  • 设置缓冲区大写,设置管道名字,以及标识有多少个线程等
    1 //设置缓存区大小
    2 #define SIZE 4096
    3 //最多有多少线程
    4 #define MAX_CONNECT 128
    5 //一开始有10个线程存在
    6 int  startthreadnum = 10;
    7 //管道名字
    8 char  pipename[128] = "\\\\.\\Pipe\\cloudpipe";
    1 //文件路径
    2 #define  path  "C:\\Program Files\\Apache Software Foundation\\Apache2.2\\cgi-bin\\kaifang.txt"
    3 //查询结果存放的路径
    4 char randpath[1000] = "";
    5 //全局的二级指针
    6 char  ** g_pp;
    7 //标示有多少行
    8 int   imax = 15151574;

     

  • 创建句柄结构体
     1 //结构体,hpipe存储管道信息,hevent用于给结构体初始化,存放连接管道的信息
     2 typedef struct info
     3 {
     4     HANDLE hthread;
     5     HANDLE hpipe;
     6     HANDLE hevent;
     7 
     8 }PIPE_ST;
     9 
    10 //创建128个结构体
    11 PIPE_ST  pipeinst[MAX_CONNECT];

     

  • 随机生成文件名存放查询的结果
    1 //随机生成文件名存放查询的结果
    2 void run()
    3 {
    4     time_t ts;
    5     srand((unsigned int)time(&ts));
    6     sprintf(randpath, "C:\\Program Files\\Apache Software Foundation\\Apache2.2\\cgi-bin\\%d.txt", rand());
    7 }

     

  • 文件载入内存
     1 //载入内存
     2 void loadfromfile()
     3 {
     4     //分配指针数组
     5     g_pp = (char **)malloc(sizeof(char*)*imax);     
     6     //内存清零
     7     memset(g_pp, \0, sizeof(char*)*imax);
     8 
     9     //以读的方式打开文件
    10     FILE *pf = fopen(path, "r");
    11     if (pf == NULL)
    12     {
    13         printf("文件打开失败");
    14         return -1;
    15     }
    16     else
    17     {
    18         for (int i = 0; i < imax; i++)
    19         {
    20             char str[1024] = { 0 };
    21             //按行读取
    22             fgets(str, 1024, pf);
    23             str[1024 - 1] = \0;
    24             int  strlength = strlen(str);
    25 
    26             //分配内存
    27             g_pp[i] = malloc(sizeof(char)*(strlength + 1));
    28 
    29             //拷贝到分配的内存
    30             if (g_pp[i] != NULL)
    31             {
    32                 strcpy(g_pp[i], str);
    33             }
    34         }
    35         fclose(pf);//关闭
    36     }
    37 }

     

  • 查询函数
     1 //查询
     2 void search(char *str,char * randpath)
     3 {
     4     //写的模式打开
     5     FILE *pf = fopen(randpath, "w");
     6     if (g_pp != NULL)
     7     {
     8 
     9         for (int i = 0; i < imax; i++)
    10         {
    11             if (g_pp[i] != NULL)
    12             {
    13                 //查询
    14                 char *p = strstr(g_pp[i], str);
    15                 if (p != NULL)
    16                 {
    17                     fputs(g_pp[i], pf);//输出到文件
    18                 }
    19             }
    20         }
    21     }
    22     fclose(pf);
    23 }

     

  • 线程函数,查询结果写入随机文件,文件名再写入管道
     1 //线程函数
     2 DWORD WINAPI severThread(void *lp)
     3 {
     4     //读取到的个数
     5     DWORD nread = 0;
     6     //写入的个数
     7     DWORD nwrite = 0;
     8     //用于判断IO
     9     DWORD dwbyte = 0;
    10     //缓存区
    11     char szbuf[SIZE] = { 0 };
    12     //获取当前结构体
    13     PIPE_ST curpipe = *(PIPE_ST*)lp;
    14     //利用event初始化一个结构体
    15     OVERLAPPED overlap = { 0, 0, 0, 0, curpipe.hevent };
    16 
    17     while (1)
    18     {
    19         //数据清零
    20         memset(szbuf, 0, sizeof(szbuf));
    21         //链接管道,信息写入overlap
    22         ConnectNamedPipe(curpipe.hpipe, &overlap);
    23         //等待连接完成 
    24         WaitForSingleObject(curpipe.hevent, INFINITE);
    25         //检测IO,如果IO错误则退出
    26         if (!GetOverlappedResult(curpipe.hpipe, &overlap, &dwbyte, TRUE))
    27         {
    28             break;
    29         }
    30         //读取管道中的数据到szbuf,最多读取SIZE个
    31         if (!ReadFile(curpipe.hpipe, szbuf, SIZE, &nread, NULL))
    32         {
    33             puts("read fail");
    34             break;
    35         }
    36         
    37         char searchstr[100] = { 0 };
    38         //去读查询谁
    39         sscanf(szbuf, "%s", searchstr);
    40 
    41         //路径配置
    42         run();
    43         //查询
    44         search(searchstr, randpath);
    45 
    46         //清零
    47         memset(szbuf, 0, sizeof(szbuf));
    48         //把路径写入管道
    49         sprintf(szbuf, "%s", randpath);
    50         WriteFile(curpipe.hpipe, szbuf, strlen(szbuf), &nwrite, NULL);//写入
    51         //断开与管道的连接
    52         DisconnectNamedPipe(curpipe.hpipe);
    53     }
    54     return 0;
    55 }

     

  • 初始化结构体并创建线程
     1 //初始化结构体并创建线程
     2 void start()
     3 {
     4     for (int i = 0; i < startthreadnum; i++)
     5     {
     6         //创建管道,如果同名,则操作同一个管道
     7         pipeinst[i].hpipe = CreateNamedPipeA(
     8             pipename,//管道名称
     9             PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,//管道读写属性
    10             PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,//消息模式,读模式,等待模式阻塞
    11             10,//最大个数
    12             0,//输出缓冲区大小
    13             0,//输入缓冲区大小
    14             1000,//超时,无限等待
    15             NULL);
    16         if (pipeinst[i].hpipe == INVALID_HANDLE_VALUE)
    17         {
    18             printf("\n%d失败", i);
    19             return;
    20         }
    21         //创建事件
    22         pipeinst[i].hevent = CreateEventA(NULL, FALSE, FALSE, FALSE);//创建事件
    23         //创建线程
    24         pipeinst[i].hthread = CreateThread(NULL, 0, severThread, &pipeinst[i], 0, NULL);
    25 
    26     }
    27     printf("sever start");
    28 
    29 }

     

  • 释放内存
     1 //释放内存
     2 void end()
     3 {
     4     for (int i = 0; i < 10;i++)
     5     {
     6         CloseHandle(pipeinst[i].hthread);
     7         CloseHandle(pipeinst[i].hevent);
     8         CloseHandle(pipeinst[i].hpipe);
     9     }
    10 }

     

  • 主函数
     1 //主函数
     2 void main()
     3 {
     4     //载入内存
     5     loadfromfile();
     6     //创建线程                            开始查询
     7     start();
     8     system("pause");
     9 
    10 }

     

客户端


  • 设置缓存区,以及管道名字和管道句柄
    1 //缓存区大小
    2 #define SIZE 4096
    3 //管道名字
    4 char  pipename[128] = "\\\\.\\Pipe\\cloudpipe";
    5 //管道句柄
    6 HANDLE m_pipe = NULL;

     

  • CGI编码格式转换到str中
     1 //CGI编码格式转换到str中
     2 char* change(char *str)
     3 {
     4     char *tempstr = malloc(strlen(str) + 1);
     5     int x = 0, y = 0;
     6     char assii_1, assii_2;
     7     while (tempstr[x])
     8     {
     9         if ((tempstr[x] = str[y]) == %)
    10         {
    11             if (str[y + 1] >= A)
    12             {
    13                 assii_1 = str[y + 1] - 55;
    14 
    15             }
    16             else
    17             {
    18                 assii_1 = str[y + 1] - 48;
    19             }
    20             if (str[y + 2] >= A)
    21             {
    22                 assii_2 = str[y + 2] - 55;
    23             }
    24             else
    25             {
    26                 assii_2 = str[y + 2] - 48;
    27             }
    28             tempstr[x] = assii_1 * 16 + assii_2;
    29             y += 2;
    30         }
    31         x++;
    32         y++;
    33     }
    34     tempstr[x] = \0;
    35     return tempstr;
    36 }

     

  • 主函数
     1 void main()
     2 {
     3     printf("Content-type:text/html\n\n");//换行
     4 
     5     system("ipconfig");//服务器不稳定因素,适当中断
     6 
     7     //获取表单信息,并对信息进行处理
     8     char szpost[256] = { 0 };
     9     gets(szpost);
    10     printf("%s", szpost);
    11 
    12     char*p1 = strchr(szpost, &);
    13     if (p1 != NULL)
    14     {
    15         *p1 = \0;
    16     }
    17     printf("<br>%s", szpost + 5);
    18     printf("<br>%s", change(szpost + 5));
    19 
    20     char *p2 = strchr(p1 + 1, &);
    21     if (p2 != NULL)
    22     {
    23         *p2 = \0;
    24     }
    25     printf("<br>%s", p1 + 6);
    26     printf("<br>%s", change(p1 + 6));
    27     
    28     //打开管道
    29     m_pipe = CreateFileA(pipename, //名称
    30         GENERIC_WRITE | GENERIC_READ,//读写
    31         0,//共享属性,1独有
    32         NULL,//默认安全属性
    33         OPEN_EXISTING,//打开已经存在的
    34         FILE_ATTRIBUTE_NORMAL,
    35         NULL);
    36 
    37     if (m_pipe == INVALID_HANDLE_VALUE)
    38     {
    39         printf("失败");
    40         return;
    41     }
    42 
    43     int nwrite;
    44     int nread;
    45 
    46     char winfo[1024] = { 0 };
    47     //打印数据到winfo中
    48     sprintf(winfo, "%s", change(szpost + 5));
    49 
    50     //写入管道
    51     WriteFile(m_pipe, winfo, strlen(winfo), &nwrite, NULL);
    52     memset(winfo, 0, sizeof(winfo));
    53     //读取管道
    54     ReadFile(m_pipe, winfo, 1024, &nread, NULL);
    55 ;
    56     //打开文件,并读取
    57     FILE *pf = fopen(winfo, "r");
    58     while (!feof(pf))
    59     {
    60         char ch = fgetc(pf);
    61         if (ch==\n)
    62         {
    63             puts("<br>");
    64         } 
    65         else
    66         {
    67             putchar(ch);
    68         }
    69     }
    70     fclose(pf);
    71 
    72     system("pause");
    73 }

     

完整代码:

服务器

  1 #define  _CRT_SECURE_NO_WARNINGS
  2 #include<stdio.h>
  3 #include<time.h>
  4 #include<stdlib.h>
  5 #include<Windows.h>
  6 
  7 //设置缓存区大小
  8 #define SIZE 4096
  9 //最多有多少线程
 10 #define MAX_CONNECT 128
 11 //一开始有10个线程存在
 12 int  startthreadnum = 10;
 13 //管道名字
 14 char  pipename[128] = "\\\\.\\Pipe\\cloudpipe";
 15 
 16 //文件路径
 17 #define  path  "C:\\Program Files\\Apache Software Foundation\\Apache2.2\\cgi-bin\\kaifang.txt"
 18 //查询结果存放的路径
 19 char randpath[1000] = "";
 20 //全局的二级指针
 21 char  ** g_pp;
 22 //标示有多少行
 23 int   imax = 15151574;
 24 
 25 //结构体,hpipe存储管道信息,hevent用于给结构体初始化,存放连接管道的信息
 26 typedef struct info
 27 {
 28     HANDLE hthread;
 29     HANDLE hpipe;
 30     HANDLE hevent;
 31 
 32 }PIPE_ST;
 33 
 34 //创建128个结构体
 35 PIPE_ST  pipeinst[MAX_CONNECT];
 36 
 37 //随机生成文件名存放查询的结果
 38 void run()
 39 {
 40     time_t ts;
 41     srand((unsigned int)time(&ts));
 42     sprintf(randpath, "C:\\Program Files\\Apache Software Foundation\\Apache2.2\\cgi-bin\\%d.txt", rand());
 43 }
 44 
 45 //载入内存
 46 void loadfromfile()
 47 {
 48     //分配指针数组
 49     g_pp = (char **)malloc(sizeof(char*)*imax);     
 50     //内存清零
 51     memset(g_pp, \0, sizeof(char*)*imax);
 52 
 53     //以读的方式打开文件
 54     FILE *pf = fopen(path, "r");
 55     if (pf == NULL)
 56     {
 57         printf("文件打开失败");
 58         return -1;
 59     }
 60     else
 61     {
 62         for (int i = 0; i < imax; i++)
 63         {
 64             char str[1024] = { 0 };
 65             //按行读取
 66             fgets(str, 1024, pf);
 67             str[1024 - 1] = \0;
 68             int  strlength = strlen(str);
 69 
 70             //分配内存
 71             g_pp[i] = malloc(sizeof(char)*(strlength + 1));
 72 
 73             //拷贝到分配的内存
 74             if (g_pp[i] != NULL)
 75             {
 76                 strcpy(g_pp[i], str);
 77             }
 78         }
 79         fclose(pf);//关闭
 80     }
 81 }
 82 
 83 //查询
 84 void search(char *str,char * randpath)
 85 {
 86     //写的模式打开
 87     FILE *pf = fopen(randpath, "w");
 88     if (g_pp != NULL)
 89     {
 90 
 91         for (int i = 0; i < imax; i++)
 92         {
 93             if (g_pp[i] != NULL)
 94             {
 95                 //查询
 96                 char *p = strstr(g_pp[i], str);
 97                 if (p != NULL)
 98                 {
 99                     fputs(g_pp[i], pf);//输出到文件
100                 }
101             }
102         }
103     }
104     fclose(pf);
105 }
106 
107 //线程函数
108 DWORD WINAPI severThread(void *lp)
109 {
110     //读取到的个数
111     DWORD nread = 0;
112     //写入的个数
113     DWORD nwrite = 0;
114     //用于判断IO
115     DWORD dwbyte = 0;
116     //缓存区
117     char szbuf[SIZE] = { 0 };
118     //获取当前结构体
119     PIPE_ST curpipe = *(PIPE_ST*)lp;
120     //利用event初始化一个结构体
121     OVERLAPPED overlap = { 0, 0, 0, 0, curpipe.hevent };
122 
123     while (1)
124     {
125         //数据清零
126         memset(szbuf, 0, sizeof(szbuf));
127         //链接管道,信息写入overlap
128         ConnectNamedPipe(curpipe.hpipe, &overlap);
129         //等待连接完成 
130         WaitForSingleObject(curpipe.hevent, INFINITE);
131         //检测IO,如果IO错误则退出
132         if (!GetOverlappedResult(curpipe.hpipe, &overlap, &dwbyte, TRUE))
133         {
134             break;
135         }
136         //读取管道中的数据到szbuf,最多读取SIZE个
137         if (!ReadFile(curpipe.hpipe, szbuf, SIZE, &nread, NULL))
138         {
139             puts("read fail");
140             break;
141         }
142         
143         char searchstr[100] = { 0 };
144         //去读查询谁
145         sscanf(szbuf, "%s", searchstr);
146 
147         //路径配置
148         run();
149         //查询
150         search(searchstr, randpath);
151 
152         //清零
153         memset(szbuf, 0, sizeof(szbuf));
154         //把路径写入管道
155         sprintf(szbuf, "%s", randpath);
156         WriteFile(curpipe.hpipe, szbuf, strlen(szbuf), &nwrite, NULL);//写入
157         //断开与管道的连接
158         DisconnectNamedPipe(curpipe.hpipe);
159     }
160     return 0;
161 }
162 
163 //初始化结构体并创建线程
164 void start()
165 {
166     for (int i = 0; i < startthreadnum; i++)
167     {
168         //创建管道,如果同名,则操作同一个管道
169         pipeinst[i].hpipe = CreateNamedPipeA(
170             pipename,//管道名称
171             PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,//管道读写属性
172             PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,//消息模式,读模式,等待模式阻塞
173             10,//最大个数
174             0,//输出缓冲区大小
175             0,//输入缓冲区大小
176             1000,//超时,无限等待
177             NULL);
178         if (pipeinst[i].hpipe == INVALID_HANDLE_VALUE)
179         {
180             printf("\n%d失败", i);
181             return;
182         }
183         //创建事件
184         pipeinst[i].hevent = CreateEventA(NULL, FALSE, FALSE, FALSE);//创建事件
185         //创建线程
186         pipeinst[i].hthread = CreateThread(NULL, 0, severThread, &pipeinst[i], 0, NULL);
187 
188     }
189     printf("sever start");
190 
191 }
192 
193 //释放内存
194 void end()
195 {
196     for (int i = 0; i < 10;i++)
197     {
198         CloseHandle(pipeinst[i].hthread);
199         CloseHandle(pipeinst[i].hevent);
200         CloseHandle(pipeinst[i].hpipe);
201     }
202 }
203 
204 //主函数
205 void main()
206 {
207     //载入内存
208     loadfromfile();
209     //创建线程                            开始查询
210     start();
211     system("pause");
212 
213 }

客户端

  1 #define  _CRT_SECURE_NO_WARNINGS
  2 #include<stdio.h>
  3 #include<time.h>
  4 #include<stdlib.h>
  5 #include<Windows.h>
  6 
  7 //缓存区大小
  8 #define SIZE 4096
  9 //管道名字
 10 char  pipename[128] = "\\\\.\\Pipe\\cloudpipe";
 11 //管道句柄
 12 HANDLE m_pipe = NULL;
 13 
 14 //CGI编码格式转换到str中
 15 char* change(char *str)
 16 {
 17     char *tempstr = malloc(strlen(str) + 1);
 18     int x = 0, y = 0;
 19     char assii_1, assii_2;
 20     while (tempstr[x])
 21     {
 22         if ((tempstr[x] = str[y]) == %)
 23         {
 24             if (str[y + 1] >= A)
 25             {
 26                 assii_1 = str[y + 1] - 55;
 27 
 28             }
 29             else
 30             {
 31                 assii_1 = str[y + 1] - 48;
 32             }
 33             if (str[y + 2] >= A)
 34             {
 35                 assii_2 = str[y + 2] - 55;
 36             }
 37             else
 38             {
 39                 assii_2 = str[y + 2] - 48;
 40             }
 41             tempstr[x] = assii_1 * 16 + assii_2;
 42             y += 2;
 43         }
 44         x++;
 45         y++;
 46     }
 47     tempstr[x] = \0;
 48     return tempstr;
 49 }
 50 
 51 
 52 void main()
 53 {
 54     printf("Content-type:text/html\n\n");//换行
 55 
 56     system("ipconfig");//服务器不稳定因素,适当中断
 57 
 58     //获取表单信息,并对信息进行处理
 59     char szpost[256] = { 0 };
 60     gets(szpost);
 61     printf("%s", szpost);
 62 
 63     char*p1 = strchr(szpost, &);
 64     if (p1 != NULL)
 65     {
 66         *p1 = \0;
 67     }
 68     printf("<br>%s", szpost + 5);
 69     printf("<br>%s", change(szpost + 5));
 70 
 71     char *p2 = strchr(p1 + 1, &);
 72     if (p2 != NULL)
 73     {
 74         *p2 = \0;
 75     }
 76     printf("<br>%s", p1 + 6);
 77     printf("<br>%s", change(p1 + 6));
 78     
 79     //打开管道
 80     m_pipe = CreateFileA(pipename, //名称
 81         GENERIC_WRITE | GENERIC_READ,//读写
 82         0,//共享属性,1独有
 83         NULL,//默认安全属性
 84         OPEN_EXISTING,//打开已经存在的
 85         FILE_ATTRIBUTE_NORMAL,
 86         NULL);
 87 
 88     if (m_pipe == INVALID_HANDLE_VALUE)
 89     {
 90         printf("失败");
 91         return;
 92     }
 93 
 94     int nwrite;
 95     int nread;
 96 
 97     char winfo[1024] = { 0 };
 98     //打印数据到winfo中
 99     sprintf(winfo, "%s", change(szpost + 5));
100 
101     //写入管道
102     WriteFile(m_pipe, winfo, strlen(winfo), &nwrite, NULL);
103     memset(winfo, 0, sizeof(winfo));
104     //读取管道
105     ReadFile(m_pipe, winfo, 1024, &nread, NULL);
106 ;
107     //打开文件,并读取
108     FILE *pf = fopen(winfo, "r");
109     while (!feof(pf))
110     {
111         char ch = fgetc(pf);
112         if (ch==\n)
113         {
114             puts("<br>");
115         } 
116         else
117         {
118             putchar(ch);
119         }
120     }
121     fclose(pf);
122 
123     system("pause");
124 }

 

以上是关于82.管道实现cgi内存多线程查询的主要内容,如果未能解决你的问题,请参考以下文章

如何让 Python 多线程管道使用 90% 的可用内存?

81.内存模式实现cgi查询

进程间通信方式及特点

Java多线程-管道流实现线程间通信

java多线程通过管道流实现不同线程之间的通信

线程与进程