程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 編程綜合問答 >> 重疊 命名管道-windows 重疊IO 命名管道程序疑問?

重疊 命名管道-windows 重疊IO 命名管道程序疑問?

編輯:編程綜合問答
windows 重疊IO 命名管道程序疑問?

我寫了一個命名管道通信例子,但是現在有兩個疑問?
疑問1 : 為什麼我的程序只能由客戶端向服務器發送數據,服務端不能向客戶端發送數據呢?服務端顯示發送成功,但是客戶端相應的可讀事件不能被觸發。
疑問2 : 偶爾出現客戶端向服務器發送數據的時候 前一兩個包丟失。

服務端代碼:

 #include "stdafx.h"

#include <windows.h> 
#include <stdio.h>
#include <tchar.h>
#include <strsafe.h>

#define CONNECTING_STATE 3
#define READING_STATE 1 
#define WRITING_STATE 2 
#define INSTANCES 1
#define PIPE_TIMEOUT 5000
#define BUFSIZE 4096

typedef struct 
{ 
   OVERLAPPED oOverlap; 
   HANDLE hPipeInst; 

} PIPEINST, *LPPIPEINST; 


VOID DisconnectAndReconnect(DWORD); 
BOOL ConnectToNewClient(HANDLE, LPOVERLAPPED); 

bool PostRecvRequest(LPPIPEINST hInst)
{
    if (NULL == hInst)
        return false;

    char buf[1] = {0};
    DWORD dwBytesReaded = 0;
    if (!ReadFile(hInst->hPipeInst, buf, 1, &dwBytesReaded, &hInst->oOverlap))
    {
        DWORD err = GetLastError();
        if (err != ERROR_IO_PENDING)
        {
            printf("client ReadFile error : %d \n", err);
            return false;
        }
    }

    return true;
}
bool IsNamedPipeCanRecv(LPPIPEINST hInst)
{
    if (NULL == hInst)
        return false;

    if (WAIT_OBJECT_0 ==WaitForSingleObject(hInst->oOverlap.hEvent, INFINITE))
    {
        return true;
    }
    ResetEvent(hInst->oOverlap.hEvent);

    return false;
}

DWORD WINAPI RecvThread(LPVOID param)
{
    LPPIPEINST hInst = (LPPIPEINST) param;
    if (hInst)
    {
        while(1)
        {
            if (IsNamedPipeCanRecv(hInst))
            {
                char buf[1024] = {0};
                DWORD dwBytesReaded = 0;
                ReadFile(hInst->hPipeInst, buf, 1024, &dwBytesReaded, NULL);
                printf("Server recv : %s\n", buf);
            }

            PostRecvRequest(hInst);
        }

    }

    return 0;
}

PIPEINST Pipe[INSTANCES]; 
HANDLE hEvents[INSTANCES]; 

int _tmain(int argc, _TCHAR* argv[])
{ 
   LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); 

   for (int i = 0; i < INSTANCES; i++) 
   { 

   // Create an event object for this instance. 
      hEvents[i] = CreateEvent( 
         NULL,    // default security attribute 
         TRUE,    // manual-reset event 
         TRUE,    // initial state = signaled 
         NULL);   // unnamed event object 

      if (hEvents[i] == NULL) 
      {
         printf("CreateEvent failed with %d.\n", GetLastError()); 
         return 0;
      }

      Pipe[i].oOverlap.hEvent = hEvents[i]; 

      Pipe[i].hPipeInst = CreateNamedPipe( 
         lpszPipename,            // pipe name 
         PIPE_ACCESS_DUPLEX |     // read/write access 
         FILE_FLAG_OVERLAPPED,    // overlapped mode 
         PIPE_TYPE_MESSAGE |      // message-type pipe 
         PIPE_READMODE_MESSAGE |  // message-read mode 
         PIPE_WAIT,               // blocking mode 
         INSTANCES,               // number of instances 
         BUFSIZE*sizeof(TCHAR),   // output buffer size 
         BUFSIZE*sizeof(TCHAR),   // input buffer size 
         PIPE_TIMEOUT,            // client time-out 
         NULL);                   // default security attributes 

      if (Pipe[i].hPipeInst == INVALID_HANDLE_VALUE) 
      {
         printf("CreateNamedPipe failed with %d.\n", GetLastError());
         return 0;
      }

     ConnectToNewClient( 
         Pipe[i].hPipeInst, 
         &Pipe[i].oOverlap); 

   } 

   HANDLE hThread = CreateThread(0, 0, RecvThread, &Pipe[0], 0, 0);

   while (1)
   {
       char buf[1024];
       scanf("%s", buf);
       DWORD dw;
       BOOL b =  WriteFile(Pipe[0].hPipeInst, buf, strlen(buf), &dw, &Pipe[0].oOverlap);
       printf("send(%d:%d) : %s\n", dw, b, buf);
   }

  return 0; 
} 

VOID DisconnectAndReconnect(DWORD i) 
{ 
// Disconnect the pipe instance. 

   if (! DisconnectNamedPipe(Pipe[i].hPipeInst) ) 
   {
      printf("DisconnectNamedPipe failed with %d.\n", GetLastError());
   }

// Call a subroutine to connect to the new client. 

   ConnectToNewClient( 
      Pipe[i].hPipeInst, 
      &Pipe[i].oOverlap); 

} 

BOOL ConnectToNewClient(HANDLE hPipe, LPOVERLAPPED lpo) 
{ 
   BOOL fConnected, fPendingIO = FALSE; 

// Start an overlapped connection for this pipe instance. 
   fConnected = ConnectNamedPipe(hPipe, lpo); 

// Overlapped ConnectNamedPipe should return zero. 
   if (fConnected) 
   {
      printf("ConnectNamedPipe failed with %d.\n", GetLastError()); 
      return 0;
   }

   switch (GetLastError()) 
   { 
   // The overlapped connection in progress. 
      case ERROR_IO_PENDING: 
         fPendingIO = TRUE; 
         break; 

   // Client is already connected, so signal an event. 

      case ERROR_PIPE_CONNECTED: 
         if (SetEvent(lpo->hEvent)) 
            break; 

   // If an error occurs during the connect operation... 
      default: 
      {
         printf("ConnectNamedPipe failed with %d.\n", GetLastError());
         return 0;
      }
   } 

   return fPendingIO; 
}

客戶端代碼

 #include "stdafx.h"

#include <windows.h> 
#include <stdio.h>
#include <conio.h>
#include <tchar.h>

#define BUFSIZE 512

typedef struct 
{ 
    OVERLAPPED oOverlap; 
    HANDLE hPipeInst; 
} PIPEINST, *LPPIPEINST; 

bool PostRecvRequest(LPPIPEINST hInst)
{
    if (NULL == hInst)
        return false;

    char buf[1] = {0};
    DWORD dwBytesReaded = 0;
    if (!ReadFile(hInst->hPipeInst, buf, 1, &dwBytesReaded, &hInst->oOverlap))
    {
        DWORD err = GetLastError();
        if (err != ERROR_IO_PENDING)
        {
            // 109 管道已結束
            printf("client ReadFile error : %d \n", err);
            return false;
        }
    }

    return true;
}
bool IsNamedPipeCanRecv(LPPIPEINST hInst)
{
    if (NULL == hInst)
        return false;

    if (WAIT_OBJECT_0 ==WaitForSingleObject(hInst->oOverlap.hEvent, INFINITE))
    {
        return true;
    }
    ResetEvent(hInst->oOverlap.hEvent);

    return false;
}

DWORD WINAPI RecvThread(LPVOID param)
{
    LPPIPEINST hInst = (LPPIPEINST) param;
    if (hInst)
    {
        while(1)
        {
            if (IsNamedPipeCanRecv(hInst))
            {
                char buf[1024] = {0};
                DWORD dwBytesReaded = 0;
                ReadFile(hInst->hPipeInst, buf, 1024, &dwBytesReaded, NULL);
                printf("Client recv : %s\n", buf);
            }

            PostRecvRequest(hInst);
        }
    }

    return 0;
}


int _tmain(int argc, _TCHAR* argv[]) 
{ 
    PIPEINST Pipe;
    Pipe.oOverlap.hEvent =   CreateEvent( 
        NULL,    // default security attribute 
        TRUE,    // manual-reset event 
        FALSE,    // initial state = signaled 
        NULL);   // unnamed event object 
   LPTSTR lpvMessage=TEXT("Default message from client."); 
   BOOL   fSuccess = FALSE; 
   DWORD 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) 
   { 
      Pipe.hPipeInst = CreateFile( 
         lpszPipename,   // pipe name 
         GENERIC_READ | GENERIC_WRITE,  // read and write access  
         0,              // no sharing 
         NULL,           // default security attributes
         OPEN_EXISTING,  // opens existing pipe 
         FILE_FLAG_OVERLAPPED,              // default attributes 
         NULL);          // no template file 

   // Break if the pipe handle is valid. 

      if ( Pipe.hPipeInst != INVALID_HANDLE_VALUE) 
         break; 

      // Exit if an error other than ERROR_PIPE_BUSY occurs. 

      if (GetLastError() != ERROR_PIPE_BUSY) 
      {
         _tprintf( TEXT("Could not open pipe. GLE=%d\n"), GetLastError() ); 
         return -1;
      }

      // All pipe instances are busy, so wait for 20 seconds. 

      if ( ! WaitNamedPipe(lpszPipename, 20000)) 
      { 
         printf("Could not open pipe: 20 second wait timed out."); 
         return -1;
      } 
   } 

// The pipe connected; change to message-read mode. 

   dwMode = PIPE_READMODE_MESSAGE | PIPE_WAIT; 
   fSuccess = SetNamedPipeHandleState( 
       Pipe.hPipeInst,    // pipe handle 
      &dwMode,  // new pipe mode 
      NULL,     // don't set maximum bytes 
      NULL);    // don't set maximum time 
   if ( ! fSuccess) 
   {
      _tprintf( TEXT("SetNamedPipeHandleState failed. GLE=%d\n"), GetLastError() ); 
      return -1;
   }

// Send a message to the pipe server. 
    PostRecvRequest(&Pipe);
   HANDLE hThread = CreateThread(0, 0, RecvThread, &Pipe, 0, 0);

   while (1)
   {
       char buf[1024];
       scanf("%s", buf);
       DWORD dw;
       WriteFile(Pipe.hPipeInst, buf, strlen(buf), &dw, NULL);
       printf("send(%d) : %s\n", dw, buf);
   }


   return 0; 
}

最佳回答:


你客戶端也要像服務端那樣也創建一個對應事件的管道,然後讓服務端反向給你數據。

oyljerry
lzg13541043726
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved