2010-06-08 4 views
7

Mi sembra di avere un problema di named pipe 101. Ho una configurazione molto semplice per connettere una pipe denominata simplex che trasmette da un'applicazione C++ non gestita ad un'app gestita da C#. La pipe si connette, ma non posso inviare un "messaggio" attraverso la pipe a meno che non chiuda l'handle che appare per svuotare il buffer e passare il messaggio. È come se il messaggio fosse bloccato. Ho provato a invertire i ruoli di client/server e invocarli con diverse combinazioni di Flag senza fortuna. Posso facilmente inviare messaggi nella direzione opposta da C# gestito a C++ non gestito. Qualcuno ha qualche idea. Qualcuno di voi può inviare con successo messaggi dal C++ non gestito a C# gestito? Riesco a trovare un sacco di esempi di tubi intrappolati o non gestiti, ma non inter-gestiti da/per unamanged - solo crediti per essere in grado di farlo.Come si invia una stringa di pipe denominata da umnanaged a spazio di codice gestito?

Nelle inserzioni, ho omesso gran parte del materiale del wrapper per chiarezza. I bit chiave che ritengo rilevanti sono i metodi di connessione/creazione/lettura e scrittura del tubo. Non preoccuparti troppo di bloccare/infilare qui.

C# Server lato

// 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++ lato client

// 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"); 
    ... 

risposta

8

sr.ReadLine() si aspetta di vedere un carattere di fine riga (s) per conoscere la fine della linea. Poiché non riceve né la nuova riga né la fine del flusso, ne attende di più. Prova:

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

o alcuni dei metodi sr.Read().

+0

Questo è tutto! Funziona tutto ora, molte grazie. Ho completamente dimenticato la necessità del newline, ero troppo concentrato sulla meccanica del pipe (layer-1). Ho dimenticato il formato del messaggio (layer-2). – user320240