多线程命名管道通信的实现

 

转载自: http://www.cnblogs.com/xinhaijulan/archive/2010/07/31/1789147.html

 

上篇介绍了【多线程命名管道通信的设计 】,本篇进行多线程命名管道通信的实现。
服务端实现如下:

创建创建命名管道实例线程

代码 
 // Handle of create Named Pipe thread.
  HANDLE hThreadCreatePipes;
 
  // Create Named Pipe thread .
  hThreadCreatePipes = CreateThread( 
         NULL,              // no security attribute 
          0,                 // default stack size 
          FUNCreatePipes,    // thread proc
          this,              // thread parameter 
          0,                 // not suspended 
         NULL);             // returns thread ID 
 // Close Handle.
 CloseHandle(hThreadCreatePipes); 
 // Set handle null.
 hThreadCreatePipes = NULL;


 

创建命名管道并创建监听管道线程:    

 

代码 
 DWORD WINAPI FUNCreatePipes(LPVOID lpParameter);
 DWORD WINAPI FUNCreatePipes(LPVOID lpParameter)
 {
         BOOL   fConnected = FALSE; 
         LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\MyPipe"); 
         
         HANDLE hPipeServer;
         HANDLE hThreadListenPipes;        
         while(TRUE)
         {                
                 hPipeServer = 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  
                         BUFSIZ,                   // output buffer size 
                         BUFSIZ,                   // input buffer size 
                         0,                        // client time-out 
                         NULL);                    // default security attribute 
                 
                 if (hPipeServer == INVALID_HANDLE_VALUE) 
                 {
                         AfxMessageBox("Create named pipes failed.");
                         return -1;
                 }
 
                 // 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(hPipeServer, NULL);
                 if (fConnected) 
                 {
                         // Create listen pipes thread. 
                         hThreadListenPipes = CreateThread( 
                                 NULL,              // no security attribute 
                                 0,                 // default stack size 
                                 FunListenPipes,    // thread proc
                                 hPipeServer,       // thread parameter 
                                 0,                 // not suspended 
                                 NULL);             // returns thread ID 
                                 
                         // Close handle.
                         CloseHandle(hThreadListenPipes); 
                         // Set handle null.
                         hThreadListenPipes = NULL;
                 }
                 else 
                 {
                         // Close handle.
                         CloseHandle(hPipeServer); 
                         // Set handle null.
                         hPipeServer = NULL;
                 }
         }
         return 0;
 }


监听管道,对管道数据进行读取与回写:

代码 
 DWORD WINAPI FunListenPipes(LPVOID lpParameter);
 DWORD WINAPI FunListenPipes(LPVOID lpParameter)
 {
    HANDLE hPipe = (HANDLE)lpParameter;
    
    HANDLE hHeap      = GetProcessHeap();
    TCHAR* pchRequest = (TCHAR*)HeapAlloc(hHeap, 0, BUFSIZ*sizeof(TCHAR));
    TCHAR* pchReply   = (TCHAR*)HeapAlloc(hHeap, 0, BUFSIZ*sizeof(TCHAR));
 
    DWORD cbBytesRead = 0, cbReplyBytes = 0, cbWritten = 0; 
    BOOL fSuccess = FALSE;
    
    CString strRequest = "";
    CString strReply = "";
    while (TRUE) 
    {                   
            fSuccess = ReadFile( 
                    hPipe,                                // handle to pipe 
                    pchRequest,                           // buffer to receive data 
                    BUFSIZ*sizeof(TCHAR),                 // size of buffer 
                    &cbBytesRead,                         // number of bytes read 
                    NULL);                                // not overlapped I/O 
            
            if (!fSuccess || cbBytesRead == 0)
            {   
                    break;
            }
            
            // Process the incoming message.
            GetAnswerToRequest(pchRequest, pchReply, &cbReplyBytes); 
            
            // Write the reply to the pipe. 
            fSuccess = WriteFile( 
                    hPipe,        // handle to pipe 
                    pchReply,     // 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;
            }
 
            strRequest = pchRequest;
            strReply = pchReply;
    }
 
    // 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); 
    hPipe = NULL;
 
    HeapFree(hHeap, 0, pchRequest);
    HeapFree(hHeap, 0, pchReply);
 
    return 1;
 }
 
 VOID GetAnswerToRequest( LPTSTR pchRequest, LPTSTR pchReply, LPDWORD pchBytes )
 {
     // Check the outgoing message to make sure it's not too long for the buffer.
     if (FAILED(strcpy(pchReply, pchRequest)))
     {
         *pchBytes = 0;
         pchReply[0] = 0;
         return;
     }
     *pchBytes = (lstrlen(pchReply)+1)*sizeof(TCHAR);
 }


服务端采用阻塞模式等待客户端的连接,客户端连接成功后,立即继续等待下一个客户端的连接
并进行管道的监听、管道数据的读取与写入。

以下为客户端实现:
初始化管道:

创建文件 
 CString strServerIP="This is the server ip";
 CString lpPipeName="\\\\" + strServerIP + "\\pipe\\MyPipe";
 LPTSTR lpszPipename = new TCHAR[lpPipeName.GetLength()+1];
 _tcscpy(lpszPipename, lpPipename); 
 HANDLE m_hPipeClient = CreateFile(
                 lpszPipename,
                 GENERIC_WRITE|GENERIC_READ,
                 0,
                 NULL, 
                 OPEN_EXISTING,
                 0,
                 NULL);
 if(m_hPipeClient == INVALID_HANDLE_VALUE)
 {
         CString strLastError;
         strLastError.Format("%d",GetLastError());
         AfxMessageBox("Error open pipes, the Last Error number is:"+strLastError);
         return;
 }
 else
 {
         AfxMessageBox("Success open pipes");
 }


设置管道状态

设置管道状态 
 DWORD dwMode = PIPE_READMODE_MESSAGE; 
 BOOL fSuccess = SetNamedPipeHandleState( 
         m_hPipeClient,    // pipe handle 
         &dwMode,          // new pipe mode 
         NULL,             // don't set maximum bytes 
         NULL);            // don't set maximum time 
 if ( ! fSuccess) 
 {
         AfxMessageBox("Failed SetNamedPipeHandleState");
 }


创建N个管道线程

创建N个管道线程 
 //Set thread number.
 int nThreadNumber=10;
 HANDLE m_hThreadSendReadData;
 for (int i=0;i<nThreadNumber;++i)
 {
         m_hThreadSendReadData = CreateThread(NULL,0,FunSendReadData,this,0,NULL);
         CloseHandle(m_hThreadSendReadData);
         m_hThreadSendReadData = NULL;
 }


读写管道

读写管道 
 DWORD WINAPI FunSendReadData(LPVOID lpParameter);
 DWORD WINAPI FunSendReadData(LPVOID lpParameter)
 {
   DWORD dwRead,dwWritten;
   TCHAR  chBuf[BUFSIZ]; 
   BOOL   fSuccess = FALSE; 
   DWORD cbRead, cbToWrite, cbWritten, dwMode;
   LPTSTR lpvMessage=TEXT("This is the data sent.");
   
   while(TRUE)
   {
         cbToWrite = (lstrlen(lpvMessage)+1)*sizeof(TCHAR);        
         fSuccess = WriteFile( 
                 pDlg->m_hPipeClient,    // pipe handle 
                 lpvMessage,             // message 
                 cbToWrite,              // message length 
                 &cbWritten,             // bytes written 
                 NULL);    
         if (!fSuccess)
         {
                 break;
         }
        
         do 
         { 
                 // Read from the pipe.                 
                 fSuccess = ReadFile( 
                         pDlg->m_hPipeClient,    // pipe handle 
                         chBuf,           // buffer to receive reply 
                         BUFSIZ*sizeof(TCHAR),   // size of buffer 
                         &cbRead,         // number of bytes read 
                         NULL);           // not overlapped 
                 
                 if ( ! fSuccess && GetLastError() != ERROR_MORE_DATA )
                 {
                         break; 
                 }
 
         } while (!fSuccess);  // repeat loop if ERROR_MORE_DATA 
   }
   return 0;
 }

服务端采用阻塞模式等待客户端的连接,客户端采用多个线程对管道进行数据读写。
因客户端采用多个线程对管道进行读写,故一个线程读取的数据可能并不是此线程写入数据后,服务端读取此线程刚写入的数据后再写入的数据。也就是客户端多个线程写入与读取的数据可能会串,此理论已经过测试,为解决此问题,可以在客户端写入数据时加标识,服务端读取数据后,再写入的数据带上此标识,客户端读取时可根据此标识来判断是否是写入数据后服务端返回的消息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值