代码改变世界

匿名管道 双向通信 需要两个

2013-05-07 01:52  Scott Guthrie Liu  阅读(425)  评论(0编辑  收藏  举报

http://www.cppblog.com/returnnull/archive/2007/05/11/23855.html

http://www.cppblog.com/ice197983/articles/4425.html

http://blog.163.com/kksunshine@yeah/blog/static/118612388201121154017976/

http://blog.163.com/tangmin927@126/blog/static/31537494200922043055553/

http://www.cnblogs.com/BoyXiao/archive/2011/01/01/1923828.html

View Code
#include <Windows.h>

int main(int argc, char* argv[])
{
    HANDLE hWrite;//管道的写入句柄
    HANDLE hRead; //管道的读取句柄
    HANDLE hWrite2;//管道的写入句柄
    HANDLE hRead2; //管道的读取句柄
    SECURITY_ATTRIBUTES sa;
    //总共就三个参数
    sa.bInheritHandle=TRUE; //表示可被子进程所继承
    sa.lpSecurityDescriptor=NULL; //安全描述符号一般都设置成NULL,即默认描述符
    sa.nLength=sizeof(SECURITY_ATTRIBUTES); //管道长度
    if(!CreatePipe(&hRead,&hWrite,&sa,0))
    {
        printf("创建匿名函数失败!\n");
    }

    if(!CreatePipe(&hRead2,&hWrite2,&sa,0))
    {
        printf("创建匿名函数失败!\n");
    }
    STARTUPINFO sui;
    PROCESS_INFORMATION pi;
    //调用ZeroMemory方法将该结构体中的所有成员都置为0,这是因为这个结构体的成员很多,如果开始的时候没有置为0的话,那它的值是随机的,将这样的结构体传给CreateProcess,可能会影响到执行的结果。
    memset(&sui,0,sizeof(STARTUPINFO));
    sui.cb            =sizeof(STARTUPINFO); //设置结构体的大小
    sui.dwFlags        |=STARTF_USESTDHANDLES; //该标识表示标准输入句柄,标准输出句柄和错误句柄是有用的
    sui.hStdInput    =hRead2; //将子进程的输入句柄设置成父进程的读句柄
    sui.hStdOutput    =hWrite; //将子进程的输出句柄设置成父进程的写句柄
    sui.hStdError    =GetStdHandle(STD_ERROR_HANDLE); //得到标准错误句柄,是父进程的错误句柄,该行代码在本程序中没有实际的用途意义

    //因为是匿名管道,是没有名称的管道,只有通过CreateProcess由上而下的传递管道操作句柄。
    //if(!CreateProcess(_T("c:\\windows\\system32\\cmd.exe"),NULL,NULL,NULL,TRUE,0,NULL,NULL,&sui,&pi))
    if(!CreateProcess(_T("D:\\Visual Studio 2012\\Projects\\boost测试\\Debug\\piple_child.exe"),NULL,NULL,NULL,TRUE,0,NULL,NULL,&sui,&pi))
    {
        printf("创建子进程失败!\n");
        CloseHandle(hRead);
        CloseHandle(hWrite);

        CloseHandle(hRead2);
        CloseHandle(hWrite2);

        hRead=NULL;
        hWrite=NULL;
        hRead2=NULL;
        hWrite2=NULL;
    }
    else
    {
        //创建一个新的进程的时候,系统会创建一个进程内核对象和一个线程内核对象,内核对象都有一个使用基数,初始调用的时候,都设置为1。在CreateProcess返回之前,该函数打开进程和线程的内核对象,并将进程相关的句柄放置到结构体PROCESS_INFORMATION的hProcess和hThread中,当Process在内部打开这些对象的时候,使得每个对象的使用基数增加到2了。如果在父进程中不需要使用这两个句柄,就将这个句柄进行关闭,使得使用基数减1。当子进程终结的时候,系统会在将使用基数减1,使得子进程的进程内核对象和线程内核对象的使用基数变为0,这样内核对象就可以被释放了。
        CloseHandle(pi.hProcess); //关闭子进程的句柄
        CloseHandle(pi.hThread); //关闭子进程中主线程的句柄
    }

    char *buf= "ping www.sina.com.cn\r\n";
    DWORD dwWrite;
    //进程的输入重定向到hReadPipe2,所以从hWritePipe2写入
    if(!WriteFile(hWrite2,buf,strlen(buf)+1,&dwWrite,NULL))
    {
        printf("匿名管道写入数据失败!\n");
    }

    char bufRead[1000];
    DWORD dwRead;

    while (true)
    {
        //进程的输出重定向到hWritePipe1,所以从hReadPipe1读取
        if(!ReadFile(hRead,bufRead,1000 -1 ,&dwRead,NULL))
        {
            printf("匿名管道读取数据失败!\n");
        }
        else
        {
            bufRead[dwRead] = '\0'; 
            printf("%s\n",bufRead);
        }
    }
}
View Code
#include "stdafx.h"
#include <Windows.h>

int _tmain(int argc, _TCHAR* argv[])
{
    DWORD dwReaded =0;                
    HANDLE hRead  = GetStdHandle(STD_INPUT_HANDLE); 
    HANDLE hWrite = GetStdHandle(STD_OUTPUT_HANDLE);

    //HANDLE hRead2  = GetStdHandle(STD_INPUT_HANDLE); 
    //HANDLE hWrite2 = GetStdHandle(STD_OUTPUT_HANDLE);

    if( hRead )
    {                  
        /*'从管道接收数据*/
        const int  nBufSize = 2048;
        char        szBuf[nBufSize];

        if(ReadFile(hRead, &szBuf,nBufSize, &dwReaded, NULL))
        {
                //char buf[]="http://www.sina.com.cn";
                DWORD dwWrite;
                if(!WriteFile(hWrite,szBuf,dwReaded,&dwWrite,NULL))
                {
                    printf("写入数据失败!\n");
                }
        }

    }
    //printf("child\n");
    return 0;
}