2010-06-08 10 views
7

Wygląda na to, że mam nazwany problem z rurami 101. Mam bardzo prostą konfigurację do połączenia potoku nazwanego simplex, transmitującego z niezarządzanej aplikacji C++ do aplikacji zarządzanej C#. Rura łączy się, ale nie mogę wysłać "wiadomości" przez potok, chyba że zamknę uchwyt, który wydaje się przepłukać bufor i przekazać wiadomość. To tak, jakby wiadomość była zablokowana. Próbowałem odwrócić role klienta/serwera i wywoływać je z różnymi kombinacjami flag bez powodzenia. Mogę łatwo wysyłać wiadomości w innym kierunku od C# managed do C++ niezarządzanego. Czy ktoś ma jakiś wgląd? Czy któryś z was może skutecznie wysyłać wiadomości z C++ niezarządzanego do C# zarządzanego? Mogę znaleźć wiele przykładów rur wewnątrzusznych lub niezarządzanych, ale nie można ich połączyć z niezmienionymi - po prostu twierdzi, że jest w stanie to zrobić.Jak wysłać nazwany ciąg rur z umnanaged do zarządzanego obszaru kodu?

W wykazach pominięto wiele elementów opakowania dla zachowania przejrzystości. Kluczowymi bitami, które moim zdaniem są istotne, są metody łączenia/tworzenia/odczytu i zapisu rur. Nie przejmuj się tutaj zbytnio blokowaniem/wątkami.

C# po stronie serwera

// This runs in its own thread and so it is OK to block 
    private void ConnectToClient() 
    { 
     // This server will listen to the sending client 
     if (m_InPipeStream == null) 
     { 
      m_InPipeStream = 
       new NamedPipeServerStream("TestPipe", PipeDirection.In, 1); 
     } 

     // Wait for client to connect to our server 
     m_InPipeStream.WaitForConnection(); 

     // Verify client is running 
     if (!m_InPipeStream.IsConnected) 
     { 
      return; 
     } 

     // Start listening for messages on the client stream 
     if (m_InPipeStream != null && m_InPipeStream.CanRead) 
     { 
      ReadThread = new Thread(new ParameterizedThreadStart(Read)); 
      ReadThread.Start(m_InPipeStream); 
     } 
    } 


    // This runs in its own thread and so it is OK to block 
    private void Read(object serverObj) 
    { 
     NamedPipeServerStream pipeStream = (NamedPipeServerStream)serverObj; 
     using (StreamReader sr = new StreamReader(pipeStream)) 
     { 
      while (true) 
      { 
       string buffer = "" ; 
       try 
       { 
        // Blocks here until the handle is closed by the client-side!! 
        buffer = sr.ReadLine(); // <<<<<<<<<<<<<< Sticks here 
       } 
       catch 
       { 
        // Read error 
        break; 
       } 

       // Client has disconnected? 
       if (buffer == null || buffer.Length == 0) 
        break; 

       // Fire message received event if message is non-empty 
       if (MessageReceived != null && buffer != "") 
       { 
        MessageReceived(buffer); 
       } 
      } 
     } 
    } 

C++ po stronie klienta

// Static - running in its own thread. 
    DWORD CNamedPipe::ListenForServer(LPVOID arg) 
    { 
     // The calling app (this) is passed as the parameter 
     CNamedPipe* app = (CNamedPipe*)arg; 

     // Out-Pipe: connect as a client to a waiting server 
     app->m_hOutPipeHandle = 
     CreateFile("\\\\.\\pipe\\TestPipe", 
       GENERIC_WRITE, 
       0, 
       NULL, 
       OPEN_EXISTING, 
       FILE_ATTRIBUTE_NORMAL, 
       NULL); 
     // Could not create handle 
     if (app->m_hInPipeHandle == NULL || 
      app->m_hInPipeHandle == INVALID_HANDLE_VALUE) 
     { 
      return 1; 
     } 

     return 0; 
    } 


    // Sends a message to the server 
    BOOL CNamedPipe::SendMessage(CString message) 
    { 
    DWORD dwSent; 

     if (m_hOutPipeHandle == NULL || 
      m_hOutPipeHandle == INVALID_HANDLE_VALUE) 
     { 
      return FALSE; 
     } 
     else 
     { 
      BOOL bOK = 
       WriteFile(m_hOutPipeHandle, 
          message, message.GetLength()+1, &dwSent, NULL); 
      //FlushFileBuffers(m_hOutPipeHandle);    // <<<<<<< Tried this 
      return (!bOK || (message.GetLength()+1) != dwSent) ? FALSE : TRUE; 
     } 
    } 


    // Somewhere in the Windows C++/MFC code... 
    ... 
    // This write is non-blocking. It just passes through having loaded the pipe. 
    m_pNamedPipe->SendMessage("Hi de hi"); 
    ... 

Odpowiedz

8

sr.ReadLine() spodziewa się postać (s) nowalinia wiedzieć do końca linii. Ponieważ nie otrzymuje ani nowej linii ani końca strumienia, czeka na więcej. Spróbuj:

m_pNamedPipe->SendMessage("Hi de hi\n") 

lub niektórych sr.Read() metody.

+0

To wszystko! Wszystko działa teraz, wielkie dzięki. Całkowicie zapomniałem o potrzebie nowej linii, byłem zbyt skupiony na mechanice rury (warstwa-1), że zapomniałem o formacie wiadomości (warstwa-2). – user320240

Powiązane problemy