命名管道实践

电脑杂谈  发布时间:2020-07-25 18:01:42  来源:网络整理

成都哪儿有卖自来水管道堵漏器,管道修补器_创建命名管道_双拥模范城(县)创建命名

管道是进程之间的一种通信机制. Windows,Linux和UNIX都使用此机制.

管道是通过I / O接口访问的字节流. 创建管道后,可以使用操作系统的任何读取或写入I / O系统调用来读取或写入管道. 创建管道的过程称为管道服务器,连接到管道的过程是管道客户端. 一个进程将数据写入管道后,另一进程可以从管道的另一端读取数据. Linux管道通过返回两个文件描述符来实现双向I / O,而Windows管道使用单个句柄(类似于Linux文件描述符)来支持双向I / O,这比Linux管道复杂得多.

匿名管道只能用于相关进程(例如父进程和子进程,同级进程)之间的通信,并且在存储区域中建立. 该过程终止后,匿名管道消失. 匿名管道允许相关的进程相互传输信息. 通常,匿名管道用于重定向子流程的标准输入和输出,以促进与父流程的数据交换. 为了双向交换数据,必须创建两个匿名通道. 父进程使用写入句柄将数据写入管道,子进程使用读取句柄从管道读取数据,相应的子进程使用写入句柄将数据写入另一个管道,而父进程使用读取句柄从管道读取数据的句柄. 匿名管道是将标准输入和输出重定向到同一计算机上关联进程的子进程的有效方法,但是它们不能在网络环境中或未关联进程之间使用.

命名管道是用于管道服务器与一个或多个管道客户端之间的单向或双向通信的命名管道. 命名管道的所有实例共享相同的管道名称,但是每个实例具有独立的缓存和句柄,并提供用于客户服务通信的单独管道. 使用实例可确保多个管道客户端可以同时使用相同的命名管道. 命名管道用于在不相关的进程和不同计算机上的进程之间传输数据. 通常,命名管道服务器进程会创建一个使用知名名称的命名管道,或者客户端会知道该名称. 知道管道名称的命名管道客户端进程会在管道的另一端打开管道创建命名管道,并遵守服务器进程指定的访问限制. 在服务器和客户端都连接到管道之后,您可以在管道上使用读取和写入操作来交换数据. 命名管道提供了一个简单的编程接口创建命名管道,用于在进程之间传输数据,而不管进程是否在同一台计算机上.

使用UNC格式: \\ Server \ Pipe \ [Path] Name,其中第一部分\\ Server指定服务器的名称,在该服务器上创建命名管道服务,并且可以表示字符串部分作为小数点(表示本机),星号(当前网络字段),域名或实际服务;第二部分\ Pipe是不可更改的硬编码字符串,例如邮筒的\ Mailslot,表示该文件在NTFS中是从属的;第三部分[Path] Name使应用程序可以唯一地定义和标识命名管道的名称,并可以设置多级目录.

命名管道提供两种基本的通信模式: 字节模式和消息模式,当在CreateNamePipe()中创建命名管道时,可以使用PIPE_TYPE_BYTE和PIPE_TYPE_MESSAGE标志进行设置. 在字节模式下,信息以连续字节流的形式在客户端和服务器之间流动. 这意味着客户端应用程序和服务器应用程序无法准确地知道在任何特定时间段内从管道读取或写入了多少字节. 在这种通信模式下,当一方将一定数量的字节写入管道后,无法保证管道的另一方可以读取相同数量的字节. 对于消息模式,客户端和服务器通过一系列不连续的数据包发送和接收数据. 从管道发送的每个消息都必须作为完整的消息读入. 建议在此处使用消息模式.

要实现命名管道服务器,必须开发一个应用程序,通过该应用程序创建一个或多个命名管道“实例”,然后由客户端进行访问. 对于服务器,管道实例实际上是用于接受来自本地或远程客户端上的应用程序的连接请求的句柄. 请按照以下步骤编写基本的服务器应用程序.

使用API​​函数CreateNamedPipe创建命名管道实例句柄.

使用API​​函数ConnectNamedPipe监视命名管道实例上客户端的连接请求.

成都哪儿有卖自来水管道堵漏器,管道修补器_创建命名管道_双拥模范城(县)创建命名

使用API​​函数ReadFile和WriteFile从客户端接收数据或将数据发送到客户端.

使用API​​函数DisconnectNamedPipe关闭命名管道的连接.

使用API​​函数CloseHandle关闭命名管道的实例句柄

在实现命名管道客户端时,必须开发一个应用程序以与命名管道服务器建立连接. 请注意,客户端无法创建命名管道实例,它可以从服务器打开现有实例. 请按照以下步骤编写基本的客户端应用程序.

使用API​​函数WaitNamePipe等待命名管道实例供您自己使用.

使用API​​函数CreateFile与命名管道建立连接.

使用API​​函数WriteFile和ReadFile分别向服务器发送数据或从服务器接收数据.

使用API​​函数CloseHandle关闭打开的命名管道会话.

m_hPipe=CreateNamedPipe(“\\\\.\\Pipe\\Test”,PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE/|PIPE_READMODE_BYTE,    1,0,0,1000,NULL);//创建命名管道
if(m_hPipe==INVALID_HANDLE_VALUE)
    m_sMessage=“Errorcreatepipe”;
else
{
    m_sMessage=“success creat pipe”;
    AfxBeginThread(ReadProc,this);//开启线程
}

成都哪儿有卖自来水管道堵漏器,管道修补器_双拥模范城(县)创建命名_创建命名管道

由于没有客户端连接到服务器时,ConnectNamedPipe()函数将无限期等待,因此,为了避免由此引起的主线程阻塞,将使用子线程ReadProc:

UINT ReadProc(LPVOIDlpVoid)
{
    char buffer[1024];//数据缓存
    DWORD ReadNum;
    CServerView* pView=(CServerView*)lpVoid;//获取
    视句柄
    if(ConnectNamedPipe(pView->m_hPipe,NULL)==FALSE)//等待客户机的连接
    {
        CloseHandle(pView->m_hPipe);//关闭管道句柄
        pView->m_sMessage=“error connect”;
        pView->Invalidate();
        return 0;
    }
    else
    {
        pView->m_sMessage=“success connect”;
        pView->Invalidate();
        //从管道读取数据
        if(ReadFile(pView->m_hPipe,buffer,sizeof(buffer),
            &ReadNum,NULL)==FALSE)
        {
            CloseHandle(pView->m_hPipe);//关闭管道句柄
            pView->m_sMessage=“read error”;
            pView->Invalidate();
        }
        else
        {
            buffer[ReadNum]='\0';//显示接收到的信息
            pView->m_sMessage=CString(buffer);
            pView->Invalidate();
        }
        return1;
    }
}

客户端与服务器建立连接后,将返回ConnectNamedPipe()并执行以下语句. 后续的ReadFile()

将负责读取客户端写入管道的数据. 完成所有操作后,服务器可以通过调用函数DisconnectNamedPipe()来终止连接:

if(DisconnectNamedPipe(m_hPipe)==FALSE)//终止连接
    m_sMessage=“error terminate connect”;
else
{
    CloseHandle(m_hPipe);//关闭管道句柄
    m_sMessage=“success terminate connect”;
}

客户端连接到服务器并发送数据

CString Message=“[testdata,fromclient]”;//要发送的数据
DWORD WriteNum;//发送的是数据长度
//等待与服务器的连接
if (WaitNamedPipe (“\\\\.\\Pipe\\Test“, NMPWAIT_WAIT_FOREVER)==FALSE)
{
    m_sMessage=“error waiting connect”;
    Invalidate();
    return;
}
//打开已创建的管道句柄
HANDLE hPipe=CreateFile(“\\\\.\\Pipe\\Test”,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(hPipe==INVALID_HANDLE_VALUE)
{
    m_sMessage=“erroropenpipe”;
    Invalidate();
    return;
}
else
{
    m_sMessage=“successopenpipe”;
    Invalidate();
}
//向管道写入数据
if(WriteFile(hPipe,Message,Message.GetLength(),    &WriteNum,NULL)==FALSE)
{
    m_sMessage="error data write";
    Invalidate();
}
else
{
    m_sMessage=“success write”;
    Invalidate();
}
CloseHandle(hPipe);

客户端接收数据

static UINT ReceiveFromPipe(LPVOID pArgs)
{
    try
    {
        CNamedPipeClientCDlg* pDlg = (CNamedPipeClientCDlg*)pArgs;
        char szBuf[1024]={0};
        memset(szBuf,0,sizeof(szBuf));
        DWORD dwRead,dwWrite;
        while(1)
        {
            if(!ReadFile(pDlg->hlPC,szBuf,1024,&dwRead,0))
                break;
            SetWindowText((HWND)pDlg->m_ReceivedEdit,szBuf);
            memset(szBuf,0,1024);
        }
    }
    catch (CMemoryException* e)
    {
        
    }
    catch (CFileException* e)
    {
    }
    catch (CException* e)
    {
    }
    
    return 0;
}

成都哪儿有卖自来水管道堵漏器,管道修补器_双拥模范城(县)创建命名_创建命名管道

由于客户端需要不断从服务器接收消息,因此需要在新线程中执行它,以防止阻塞主线程.

hlThread = AfxBeginThread(ReceiveFromPipe,this)


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-288046-1.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    热点图片
    拼命载入中...