C# – Cannot get string data to pass through NamedPipeServerStream and NamedPipeClientStream

cnet

I'm trying to achieve bi-directional, named pipe communication on my Win-XP workstation using two simple C# forms solutions. One for the client and one for the server. They appear almost identical and use NamedPipeServerStream and NamedPipeClientStream (.NET 3.5). Both client and server are set to bidirectional comms via PipeDirection.InOut

The order of start-up events is:
1) Start the server. It waits for a connection from the client.
2) Start the client and it immediately finds and connects to the server. The server, likewise, completes its connection to the client.
3) Both client and server launch their "Read" threads which in turn create instances of streamreader. These threads then call ReadLn() and block – waiting for data. In all instances, autoflush is true.

I then use streamwriter.WriteLn() to send string data from the server to the client (or vice-versa). However, the execution never returns from that call. I don't know why and any insights would be greatfully received.

I have spent considerable time studying all that there is on this subject but I'm still missing something.

Client and server code snippets are shown:

SERVER:

   private void ListenForClients()
    {
        // Only one server as this will be a 1-1 connection
        m_pipeServerStream = new NamedPipeServerStream(PipeName, PipeDirection.InOut, 1);

        // Wait for a client to connect
        m_pipeServerStream.WaitForConnection();

        // Ccould not create handle - server probably not running
        if (!m_pipeServerStream.IsConnected)
            return;

        // Create a stream writer which flushes after every write
        m_pipeServerWriter = new StreamWriter(m_pipeServerStream);
        m_pipeServerWriter.AutoFlush = true;

        Connected = true;

        // Start listening for messages
        if (m_pipeServerStream.CanRead)
        {
            ReadThread = new Thread(new ParameterizedThreadStart(Read));
            ReadThread.Start(m_pipeServerStream);
        }
    }

    /// <summary>
    /// Reads data from the client
    /// </summary>
    /// <param name="serverObj"></param>
    private void Read(object serverObj)
    {
        NamedPipeServerStream pipeStream = (NamedPipeServerStream)serverObj;
        using (StreamReader sr = new StreamReader(pipeStream))
        {
            while (true)
            {
                string buffer;
                try
                {
                    buffer = sr.ReadLine();
                }
                catch
                {
                    //read error has occurred
                    break;
                }

                //client has disconnected
                if (buffer.Length == 0)
                    break;

                //fire message received event
                if (MessageReceived != null)
                {
                    MessageReceived(buffer);
                }
            }
        }
    }

    /// <summary>
    /// Sends a message to the connected client
    /// </summary>
    /// <param name="message">the message to send</param>
    public void SendMessage(string message)
    {
        if (m_pipeServerWriter != null)
        {
            m_pipeServerWriter.WriteLine(message);
            m_pipeServerWriter.Flush();
        }
    }

CLIENT:

   private void ConnectToServer()
    {
        // Seek out the one server
        m_pipeClientStream = new NamedPipeClientStream(".", PipeName, PipeDirection.InOut);

        // Connect to the waiting server
        m_pipeClientStream.Connect();

        // Ccould not create handle - server probably not running
        if (!m_pipeClientStream.IsConnected)
            return;

        // Create a stream writer which flushes after every write
        m_pipeClientWriter = new StreamWriter(m_pipeClientStream);
        m_pipeClientWriter.AutoFlush = true;

        Connected = true;

        // Start listening for messages
        if (m_pipeClientStream.CanRead)
        {
            ReadThread = new Thread(new ParameterizedThreadStart(Read));
            ReadThread.Start(m_pipeClientStream);
        }
    }

    /// <summary>
    /// Reads data from the server
    /// </summary>
    private void Read(object serverObj)
    {
        NamedPipeClientStream pipeStream = (NamedPipeClientStream)serverObj;
        using (StreamReader sr = new StreamReader(pipeStream))
        {
            while (true)
            {
                string buffer;
                try
                {
                    buffer = sr.ReadLine();
                }
                catch
                {
                    //read error has occurred
                    break;
                }

                //client has disconnected
                if (buffer.Length == 0)
                    break;

                //fire message received event
                if (MessageReceived != null)
                {
                    MessageReceived(buffer);
                }
            }
        }
    }

    /// <summary>
    /// Sends a message to the connected server
    /// </summary>
    /// <param name="message"></param>
    public void SendMessage(string message)
    {
        if (m_pipeClientWriter != null)
        {
            m_pipeClientWriter.WriteLine(message);
            m_pipeClientWriter.Flush();
        }
    }

Best Answer

Try setting the Async flag on the streams:

NamedPipeClientStream(".", PipeName, PipeDirection.InOut, PipeOptions.Asynchronous);