Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you read and write with a single Named Pipe client?

I've written a little apllication that creates a named pipe server and a client that connects to it. You can send data to the server, and the server reads it successfully.

The next thing I need to do is receive messages from the server, so I've got another thread that spawns and sits and waits for incoming data.

The problem is that whilst the thread is sat waiting for incoming data, you can no longer send messages to the server as it hangs on the WriteLine call as I assume the pipe is now tied up checking for data.

So is it just that I'm not approaching this properly? Or are named pipes not meant to be used like this? The examples I've seen on named pipes seem to only go one way, a client sends and a server receives, although you can specify the direction of a pipe as In, Out or both.

Any help, pointers or suggestions would be appreciated!

Heres' the code so far:

// Variable declarations
NamedPipeClientStream pipeClient;
StreamWriter swClient;
Thread messageReadThread;
bool listeningStopRequested = false;

// Client connect
public void Connect(string pipeName, string serverName = ".")
{
    if (pipeClient == null)
    {
        pipeClient = new NamedPipeClientStream(serverName, pipeName, PipeDirection.InOut);
        pipeClient.Connect();
        swClient = new StreamWriter(pipeClient);
        swClient.AutoFlush = true;
    }

    StartServerThread();
}

// Client send message
public void SendMessage(string msg)
{
    if (swClient != null && pipeClient != null && pipeClient.IsConnected)
    {
        swClient.WriteLine(msg);
        BeginListening();
    }
}


// Client wait for incoming data
public void StartServerThread()
{
    listeningStopRequested = false;
    messageReadThread = new Thread(new ThreadStart(BeginListening));
    messageReadThread.IsBackground = true;
    messageReadThread.Start();
}

public void BeginListening()
{
    string currentAction = "waiting for incoming messages";

    try
    {
        using (StreamReader sr = new StreamReader(pipeClient))
        {
            while (!listeningStopRequested && pipeClient.IsConnected)
            {
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    RaiseNewMessageEvent(line);
                    LogInfo("Message received: {0}", line);
                }
            }
        }

        LogInfo("Client disconnected");

        RaiseDisconnectedEvent("Manual disconnection");
    }
    // Catch the IOException that is raised if the pipe is
    // broken or disconnected.
    catch (IOException e)
    {
        string error = "Connection terminated unexpectedly: " + e.Message;
        LogError(currentAction, error);
        RaiseDisconnectedEvent(error);
    }
}
like image 652
Iain Ward Avatar asked Dec 08 '11 17:12

Iain Ward


1 Answers

You cannot read from one thread and write on another thread to the same pipe object. So while you could create a protocol where the listening position changes depending on the data you're sending, you cannot do both at the same time. You will need a client and server pipe on both sides to do this.

like image 145
John Doe Avatar answered Oct 01 '22 22:10

John Doe