2010-06-08 3 views
7

Ich habe anscheinend ein Named Pipes 101 Problem. Ich habe eine sehr einfache Einrichtung, um eine Simplex Named Pipe, die von einer nicht verwalteten C++ - Anwendung sendet, mit einer C# verwalteten App zu verbinden. Die Pipe verbindet sich, aber ich kann keine "Nachricht" durch die Pipe senden, wenn ich nicht den Griff schließe, der den Puffer zu spülen scheint und die Nachricht weitergibt. Es ist wie die Nachricht blockiert ist. Ich habe versucht, die Rollen von Client/Server umzukehren und sie mit verschiedenen Flaggenkombinationen ohne Glück aufzurufen. Ich kann problemlos Nachrichten in der anderen Richtung von C# verwaltet nach C++ unmanaged senden. Hat jemand einen Einblick? Kann jemand von euch erfolgreich Nachrichten von C++ unmanaged zu C# verwalten? Ich kann viele Beispiele für intraangegangene oder nicht gemanagte Pipes finden, aber nicht von/zu nicht gemanagt - nur behauptet, dies tun zu können.Wie senden Sie eine Named Pipe-Zeichenfolge von umanagered zu verwaltetem Coderaum?

In den Auflistungen habe ich viel Wrapper-Zeug für Klarheit weggelassen. Die Schlüsselbits, die ich für relevant halte, sind die Pipe-Verbindungs-/Erzeugungs-/Lese- und Schreib-Methoden. Mach dir nicht zu viele Gedanken über das Blockieren/Threading hier.

C# Server-Seite

// 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++ Client-Seite

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

Antwort

8

sr.ReadLine() erwartet ein Newline-Zeichen (s) zu sehen, das Ende der Linie zu kennen. Da es weder neue Zeile noch End-of-Stream erhält, wartet es auf mehr. Versuchen:

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

oder einige der sr.Read() Methoden.

+0

Das war's! Es funktioniert jetzt alles, vielen Dank. Ich habe die Notwendigkeit für den Zeilenumbruch komplett vergessen, ich war zu sehr auf die Mechanik der Pipe fokussiert (Layer-1) Ich habe das Nachrichtenformat vergessen (Layer-2). – user320240

Verwandte Themen