zoukankan      html  css  js  c++  java
  • Windows进程间通信—命名管道

    命名管道是通过网络来完成进程间的通信,它屏蔽了底层的网络协议细节。我们在不了解网络协议的情况下,也可以利用命名管道来实现进程间的通信。与Socket网络通信相比,命名管道不再需要编写身份验证的代码。将命名管道作为一种网络编程方案时,它实际上建立了一个C/S通信体系,并在其中可靠的传输数据。命名管道服务器和客户机的区别在于:服务器是唯一一个有权创建命名管道的进程,也只有它能接受管道客户机的连接请求。而客户机只能同一个现成的命名管道服务器建立连接。命名管道服务器只能在WindowsNT或Windows2000上创建,不过可以是客户机。命名管道提供了两种基本通信模式,字节模式和消息模式。在字节模式中,数据以一个连续的字节流的形式在客户机和服务器之间流动。而在消息模式中,客户机和服务器则通过一系列不连续的数据单位进行数据的收发,每次在管道上发出一条消息后,它必须作为一条完整的消息读入。

    服务端代码流程:

    1、创建命名管道:CreateNamedPipe

    2、等待客户端连接:ConnectNamedPipe

    3、读取客户端请求数据:ReadFile

    4、向客户端回复数据:WriteFile

    5、关闭连接:DisconnectNamedPipe

    6、关闭管道:CloseHandle

    #include "stdafx.h"  
    #include <windows.h>  
    #include <strsafe.h>  
      
    #define BUFSIZE 4096  
      
    DWORD WINAPI InstanceThread(LPVOID);   
    VOID GetAnswerToRequest(LPTSTR, LPTSTR, LPDWORD);   
      
    int _tmain(VOID)   
    {   
        BOOL fConnected;   
        DWORD dwThreadId;   
        HANDLE hPipe, hThread;   
        LPTSTR lpszPipename = TEXT("\\.\pipe\mynamedpipe");   
      
        // The main loop creates an instance of the named pipe and   
        // then waits for a client to connect to it. When the client   
        // connects, a thread is created to handle communications   
        // with that client, and the loop is repeated.   
      
        for (;;)   
        {   
            hPipe = CreateNamedPipe(   
                lpszPipename,             // pipe name   
                PIPE_ACCESS_DUPLEX,       // read/write access   
                PIPE_TYPE_MESSAGE |       // message type pipe   
                PIPE_READMODE_MESSAGE |   // message-read mode   
                PIPE_WAIT,                // blocking mode   
                PIPE_UNLIMITED_INSTANCES, // max. instances    
                BUFSIZE,                  // output buffer size   
                BUFSIZE,                  // input buffer size   
                0,                        // client time-out   
                NULL);                    // default security attribute   
      
            if (hPipe == INVALID_HANDLE_VALUE)   
            {  
                printf("CreatePipe failed");   
                return 0;  
            }  
      
            // Wait for the client to connect; if it succeeds,   
            // the function returns a nonzero value. If the function  
            // returns zero, GetLastError returns ERROR_PIPE_CONNECTED.   
      
            fConnected = ConnectNamedPipe(hPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);   
      
            if (fConnected)   
            {   
                // Create a thread for this client.   
                hThread = CreateThread(   
                    NULL,              // no security attribute   
                    0,                 // default stack size   
                    InstanceThread,    // thread proc  
                    (LPVOID) hPipe,    // thread parameter   
                    0,                 // not suspended   
                    &dwThreadId);      // returns thread ID   
      
                if (hThread == NULL)   
                {  
                    printf("CreateThread failed");   
                    return 0;  
                }  
                else CloseHandle(hThread);   
            }   
            else  
            {  
                // The client could not connect, so close the pipe.   
                CloseHandle(hPipe);   
            }  
        }   
        return 1;   
    }   
      
    DWORD WINAPI InstanceThread(LPVOID lpvParam)   
    {   
        TCHAR chRequest[BUFSIZE];   
        TCHAR chReply[BUFSIZE];   
        DWORD cbBytesRead, cbReplyBytes, cbWritten;   
        BOOL fSuccess;   
        HANDLE hPipe;   
      
        // The thread's parameter is a handle to a pipe instance.   
      
        hPipe = (HANDLE) lpvParam;   
      
        while (1)   
        {   
            // Read client requests from the pipe.   
            fSuccess = ReadFile(   
                hPipe,        // handle to pipe   
                chRequest,    // buffer to receive data   
                BUFSIZE*sizeof(TCHAR), // size of buffer   
                &cbBytesRead, // number of bytes read   
                NULL);        // not overlapped I/O   
      
            if (! fSuccess || cbBytesRead == 0)   
                break;   
            printf((const char*)chRequest);  
      
            GetAnswerToRequest(chRequest, chReply, &cbReplyBytes);   
      
            // Write the reply to the pipe.   
            fSuccess = WriteFile(   
                hPipe,        // handle to pipe   
                chReply,      // buffer to write from   
                cbReplyBytes, // number of bytes to write   
                &cbWritten,   // number of bytes written   
                NULL);        // not overlapped I/O   
      
            if (! fSuccess || cbReplyBytes != cbWritten) break;   
        }   
      
        // Flush the pipe to allow the client to read the pipe's contents   
        // before disconnecting. Then disconnect the pipe, and close the   
        // handle to this pipe instance.   
      
        FlushFileBuffers(hPipe);   
        DisconnectNamedPipe(hPipe);   
        CloseHandle(hPipe);   
      
        return 1;  
    }  
      
    VOID GetAnswerToRequest(LPTSTR chRequest,   
                            LPTSTR chReply, LPDWORD pchBytes)  
    {  
        _tprintf( TEXT("%s
    "), chRequest );  
        StringCchCopy( chReply, BUFSIZE, TEXT("Default answer from server") );  
        *pchBytes = (lstrlen(chReply)+1)*sizeof(TCHAR);  
    }  
    /* 何问起 hovertree.com */

    客户端代码流程:

    1、打开命名管道:CreateFile

    2、等待服务端响应:WaitNamedPipe

    3、切换管道为读模式:SetNamedPipeHandleState

    4、向服务端发数据:WriteFile

    5、读服务端返回的数据:ReadFile

    6、关闭管道:CloseHandle

    #include "stdafx.h"  
    #include <windows.h>  
    #include <conio.h>  
      
      
    #define BUFSIZE 512  
      
    int _tmain(int argc, TCHAR *argv[])   
    {   
        HANDLE hPipe;   
        LPTSTR lpvMessage=TEXT("Default message from client");   
        TCHAR chBuf[BUFSIZE];   
        BOOL fSuccess;   
        DWORD cbRead, cbWritten, dwMode;   
        LPTSTR lpszPipename = TEXT("\\.\pipe\mynamedpipe");   
      
        if( argc > 1 )  
            lpvMessage = argv[1];  
      
        // Try to open a named pipe; wait for it, if necessary.   
      
        while (1)   
        {   
            hPipe = CreateFile(   
                lpszPipename,   // pipe name   
                GENERIC_READ |  // read and write access   
                GENERIC_WRITE,   
                0,              // no sharing   
                NULL,           // default security attributes  
                OPEN_EXISTING,  // opens existing pipe   
                0,              // default attributes   
                NULL);          // no template file   
      
            // Break if the pipe handle is valid.   
      
            if (hPipe != INVALID_HANDLE_VALUE)   
                break;   
      
            // Exit if an error other than ERROR_PIPE_BUSY occurs.   
      
            if (GetLastError() != ERROR_PIPE_BUSY)   
            {  
                printf("Could not open pipe");   
                return 0;  
            }  
      
            // All pipe instances are busy, so wait for 20 seconds.   
      
            if (!WaitNamedPipe(lpszPipename, 20000))   
            {   
                printf("Could not open pipe");   
                return 0;  
            }   
        }   
      
        // The pipe connected; change to message-read mode.   
      
        dwMode = PIPE_READMODE_MESSAGE;   
        fSuccess = SetNamedPipeHandleState(   
            hPipe,    // pipe handle   
            &dwMode,  // new pipe mode   
            NULL,     // don't set maximum bytes   
            NULL);    // don't set maximum time   
        if (!fSuccess)   
        {  
            printf("SetNamedPipeHandleState failed");   
            return 0;  
        }  // 何问起 hovertree.com
      
        // Send a message to the pipe server.   
      
        fSuccess = WriteFile(   
            hPipe,                  // pipe handle   
            lpvMessage,             // message   
            (lstrlen(lpvMessage)+1)*sizeof(TCHAR), // message length   
            &cbWritten,             // bytes written   
            NULL);                  // not overlapped   
        if (!fSuccess)   
        {  
            printf("WriteFile failed");   
            return 0;  
        }  
      
        do   
        {   
            // Read from the pipe.   
      
            fSuccess = ReadFile(   
                hPipe,    // pipe handle   
                chBuf,    // buffer to receive reply   
                BUFSIZE*sizeof(TCHAR),  // size of buffer   
                &cbRead,  // number of bytes read   
                NULL);    // not overlapped   
      
            if (! fSuccess && GetLastError() != ERROR_MORE_DATA)   
                break;   
      
            _tprintf( TEXT("%s
    "), chBuf );   
        } while (!fSuccess);  // repeat loop if ERROR_MORE_DATA   
      
        getch();  
      
        CloseHandle(hPipe);   
      
        return 0;   
    }  

    推荐:http://www.cnblogs.com/roucheng/p/vs2015cpp.html

  • 相关阅读:
    TestNG DataProvider的几种方法写法
    ruby操作EXCEL的简单示例
    QTP的tsr对象库文件转换成XML
    Ruby对时间的处理
    java读取YAML文件
    ruby遍历文件夹
    ruby操作excel文件
    [转载]利用ruby的Net::HTTP发起http请求并对返回包进行简单的校验
    QTP连接MySQL (转载)
    Ruby 冒泡排序
  • 原文地址:https://www.cnblogs.com/roucheng/p/windowsguandao.html
Copyright © 2011-2022 走看看