System.IO.Exception: Pipe is broken - c#

I have two .NET applications that talk to each other over a named pipe. Everything is great the first time through, but after the first message is sent, and the server is going to listen again, the WaitForConnection() method throws a System.IO.Exception with message Pipe is broken.
Why am I getting this exception here? This is my first time working with pipes, but a similar pattern has worked for me in the past with sockets.
Code ahoy!
Server:
using System.IO.Pipes;
static void main()
{
var pipe = new NamedPipeServerStream("pipename", PipeDirection.In);
while (true)
{
pipe.Listen();
string str = new StreamReader(pipe).ReadToEnd();
Console.Write("{0}", str);
}
}
Client:
public void sendDownPipe(string str)
{
using (var pipe = new NamedPipeClientStream(".", "pipename", PipeDirection.Out))
{
using (var stream = new StreamWriter(pipe))
{
stream.Write(str);
}
}
}
The first call to sendDownPipe gets the server to print the message I send just fine, but when it loops back up to listen again, it poops.

I'll post my code that seems to work - I was curious since I never did anything with pipes. I didn't find the class you name for the server-side in the relevant namespace, so here's the code based on the NamedPipeServerStream. The callback stuff is just because I couldn't be bothered with two projects.
NamedPipeServerStream s = new NamedPipeServerStream("p", PipeDirection.In);
Action<NamedPipeServerStream> a = callBack;
a.BeginInvoke(s, ar => { }, null);
...
private void callBack(NamedPipeServerStream pipe)
{
while (true)
{
pipe.WaitForConnection();
StreamReader sr = new StreamReader(pipe);
Console.WriteLine(sr.ReadToEnd());
pipe.Disconnect();
}
}
And the client does this:
using (var pipe = new NamedPipeClientStream(".", "p", PipeDirection.Out))
using (var stream = new StreamWriter(pipe))
{
pipe.Connect();
stream.Write("Hello");
}
I can repeat above block multiple times with the server running, no prob.

The problem for me has occurred when I would call pipe.WaitForConnection() from the server, after the client disconnected. The solution is to catch the IOException and call pipe.Disconnect(), and then call pipe.WaitForConnection() again:
while (true)
{
try
{
_pipeServer.WaitForConnection();
break;
}
catch (IOException)
{
_pipeServer.Disconnect();
continue;
}
}

I ran into a similar issue when I put Environment.Exit(0) at the end of my Main method, which apparently killed the entire process even though I thought the code was unreachable (because it was after a while loop waiting for a different thread to stop).

I had the same problem - it is caused by disposing server's StreamReader by Using...End Using, which also take down NamedPipeServerStream. Solution is simply don't Using...End Using it and trust in garbage collector.

Related

Is a named pipe able to do what i want to do?

This is take II, i posted the other week and my question was put on hold, i adjusted my text but could not get a review, and the system closed the original post.
Logic
Server Side: Read only - Server Opens pipe then at regular interval checks if there is content (i.e. not at end of stream) and reads info. This check has to be poll based as only during the poll is there a valid context to pass on the data..
Client Side: Write-only - Open pipe, write to pipe, close (client.exe called many times, has short life span, code below is test code), e.g. some other script will "call client.exe with info"
Can this work flow be handled in pipes ? e.g. snippet of client code shown only the first client message is seen by the "server"
If pipes can do this after coding tips as most examples are for client - servers having similar life cycles.
Code snippets
for (int i = 0; i < 10; i++)
{
//Client - simulate exe starting and ending
var client = new NamedPipeClientStream(".", "PipesOfPiece", PipeDirection.Out, PipeOptions.WriteThrough);
client.Connect();
StreamWriter writer = new StreamWriter(client);
Console.WriteLine("Client about to send message");
writer.WriteLine("Called from client i = {0}", i);
writer.Close();
client.Close();
Thread.Sleep(5000);
}
// server snippet
var server = new NamedPipeServerStream("PipesOfPiece", PipeDirection.In);
server.WaitForConnection(); <= can this we optional with code below
StreamReader reader = new StreamReader(server);
while (true)
{
// simulate start of poll code
if (server.IsConnected)
{
if (!reader.EndOfStream)
{
var line = reader.ReadToEnd();
Console.WriteLine("Server: {0}", line);
}
} // End of poll code
Thread.Sleep(1000);
}
// server snippet
var server = new NamedPipeServerStream("PipesOfPiece", PipeDirection.In);
server.WaitForConnection(); <= can this we optional with code below
StreamReader reader = new StreamReader(server);
while (true)
{
// simulate start of poll code
if (server.IsConnected)
{
if (!reader.EndOfStream)
{
var line = reader.ReadToEnd();
Console.WriteLine("Server: {0}", line);
}
} // End of poll code
Thread.Sleep(1000);
}
So I am rusty on my pipes, I am hoping that a pipe can be opened, written to then read, and the waitforconnect() is there for the cases where you want this and is optional. I suppose it all triggers around who owns the pipe, i.e. if the server opens a pipe and is waiting for someone to write for it, why does it need to wait for a connect ? (I am hoping the server is the owner so when it ends, the pipe disappears)
Without a good, minimal, complete code example that reliably reproduces whatever specific problem you are having, it is impossible to provide specific advice as to how to fix that problem. However, I can at least try to answer some of your questions about how named pipes can be used, and provide a code example to illustrate some of the concepts.
First, some rules and observations:
A pipe instance can be used for only one connection. Note that pipes inherit Stream, and streams have a very specific paradigm: you open one, read to the end, and then you're done with the stream. Some streams, like FileStream, are seekable but even there you are only ever dealing with a single resource (i.e. the original file…you can't reconnect a FileStream to a different file), and network streams aren't even seekable.
A pipe must be connected before you perform I/O on it.
You may have multiple instances of pipes with the same name (if you initialize them correctly…by default, you may only have one pipe of any given name).
Clients trying to connect to a named pipe will wait until such a pipe exists. It does not need to exist at the time the client initiates the connection.
Only one client can connect to any given instance of a pipe. Any given instance of a server pipe can only ever handle a single client during its entire lifetime (see the very first point above).
So, what about your questions?
Can this work flow be handled in pipes ?
If I understand the work-flow correctly, yes. But you need to be careful to implement it correctly.
As I understand it, you want for your server to only attempt to read from clients periodically. At the same time, you want for a client to be able to write to a pipe at any time. This can be done, but it won't be straightforward.
Note per the above that you cannot open a single server pipe, and then let multiple clients periodically connect and disconnect from that pipe. Once the first client has connected, the pipe is no longer usable. It's a stream, and that first client's disconnection causes the stream to reach its end. It's done.
Note also that while a client can attempt to connect to a pipe that doesn't exist yet, it will wait until it can. So if you want your clients to not have to wait until the polling interval has expired, you'll need to maintain a server pipe available to connect to at all times.
But you've already said that you won't be able to handle data read from the server pipe at arbitrary points in time, but rather only during your polling interval.
Because pipes don't inherently support this specific scenario, IMHO the right way to implement it is to separate the behaviors into two different components. Maintain a simple pipe server that opens a pipe, waits for a client to connect, reads whatever the client has sent, closes the pipe, and then starts over.
Then have an intermediary class that can act as the go-between for the server I/O and whatever component you have that ultimately receives the data. This intermediary will retain a copy of the data after it's been received (the pipe code will deliver it to the intermediary as soon as it's received, regardless of the polling interval); the data will then later be retrieved by the polling component on its next polling interval (i.e. when the "context" as you put it is in fact available to which to deliver the data).
I am hoping that a pipe can be opened, written to then read, and the waitforconnect() is there for the cases where you want this and is optional
Unfortunately, your hope doesn't match the reality. Pipes can be bidirectional; i.e. "written to then read". But WaitForConnect() is not optional. The server must wait for a connection before attempting to read from the pipe, and for that pipe instance it will only ever be able to receive data from a single client.
I am hoping the server is the owner so when it ends, the pipe disappears
The server process is the one that actually creates the pipe. So yes, in that sense it is the owner. And yes, when the server process is terminated, any pipes it's created are destroyed.
Below, please find a simple code example that illustrates the use of multiple and concurrent servers and clients. You can adjust the numbers of each with the declared constants at the top of the example.
When running it, note that if more clients are active than servers, the additional clients will simply wait until a server pipe is available to connect to. Once one is, they will connect and proceed normally. If there are at least as many server pipe instances as there are clients trying to connect, all of the clients are serviced concurrently.
// NOTE: as a sample program, contrary to normal and correct
// programming practices error-handling has been omitted, and
// non-awaited async methods have been declared as void.
class Program
{
private const string _kserverName = "TestSO33093954NamedPipeClients";
private const int _kmaxServerCount = 3;
private const int _kmaxClientCount = 3;
static void Main(string[] args)
{
StartServers(_kmaxServerCount);
StartClients(_kmaxClientCount);
Console.WriteLine("Clients are being started. Press return to exit program.");
Console.ReadLine();
}
private static async void StartClients(int clientCount)
{
for (int i = 0; i < clientCount; i++)
{
RunClient(i);
await Task.Delay(300);
}
}
private static async void RunClient(int instance)
{
NamedPipeClientStream client = new NamedPipeClientStream(
".", _kserverName, PipeDirection.InOut, PipeOptions.Asynchronous);
client.Connect();
ReadClient(client);
using (StreamWriter writer = new StreamWriter(client))
{
writer.AutoFlush = true;
for (int i = 0; i < 5; i++)
{
string text =
string.Format("Instance #{0}, iteration #{1}", instance, i);
Console.WriteLine("Client send: " + text);
await writer.WriteLineAsync(text);
await Task.Delay(1000);
}
client.WaitForPipeDrain();
}
}
private static async void ReadClient(Stream stream)
{
using (TextReader reader = new StreamReader(stream))
{
string line;
while ((line = await reader.ReadLineAsync()) != null)
{
Console.WriteLine("Client recv: " + line);
}
}
}
private static void StartServers(int maxServerInstances)
{
for (int i = 0; i < maxServerInstances; i++)
{
RunServer(maxServerInstances);
}
}
private static async void RunServer(int maxServerInstances)
{
while (true)
{
using (NamedPipeServerStream server = new NamedPipeServerStream(
_kserverName, PipeDirection.InOut, maxServerInstances,
PipeTransmissionMode.Byte, PipeOptions.Asynchronous))
{
await server.WaitForConnectionAsync();
byte[] buffer = new byte[1024];
int bytesRead;
Decoder decoder = Encoding.UTF8.GetDecoder();
while ((bytesRead =
await server.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
int cch = decoder.GetCharCount(buffer, 0, bytesRead);
char[] rgch = new char[cch];
decoder.GetChars(buffer, 0, bytesRead, rgch, 0);
Console.Write("Server recv: " + new string(rgch));
await server.WriteAsync(buffer, 0, bytesRead);
}
}
}
}
}
static class PipeExtensions
{
// As I am not running with .NET 4.6 yet, I need this little helper extension
// to wrap the APM-based asynchronous connection-waiting with the await-friendly
// Task-based syntax. Anyone using .NET 4.6 will have this in the framework already
public static Task WaitForConnectionAsync(this NamedPipeServerStream server)
{
return Task.Factory.FromAsync(
server.BeginWaitForConnection, server.EndWaitForConnection, null);
}
}

C# Modbus/tcp - hanging connection

I have written Windows service, which perform Modbus WriteMultipleRegisters function call over TCP using NModbus library to 3-party devices every 10 minutes (ticks of System.Threading.Timer).
Occasionally this connection hang up open usually during network problems. As the device accepts only one Modbus connection at time and others are refused, connection during all next ticks fail with SocketException - ConnectionRefused.
But the device automatically closes connections which don't respond after short time. Something must keep connection open at my side even for two days. What's more when my Service is restarted, everything is fine again. So there is definitely some forgotten open connection. But I didn't manage to reproduce this bug in dev, so I don't where/when.. connection hang up. I only know that next connection is refused.
I do the modbus function call with this part of code:
using (TcpClient client = new TcpClient(device.ip, 502))
{
using (Modbus.Device.ModbusIpMaster master = Modbus.Device.ModbusIpMaster.CreateIp(client))
{
master.WriteMultipleRegisters(500, new ushort[] { 0xFF80 });
}
}
device.ip is string containing IP address of device - it's correct, confirmed from SocketException details.
As I'm using using statement dispose is called on both objects.
I have looked trough NModbus source code and everything is disposed correctly.
Any idea how its possible that with this code connection is not closed?
I agree with nemec. If you review the documentation for TcpClient.Dispose if does not specifically mention closing the connection. It frees managed and unmanaged resources by default, but it may not correctly tear down the connection.
Try changing your code to:
using (TcpClient client = new TcpClient(device.ip, 502))
{
try
{
using (Modbus.Device.ModbusIpMaster master = Modbus.Device.ModbusIpMaster.CreateIp(client))
{
master.WriteMultipleRegisters(500, new ushort[] { 0xFF80 });
}
}
catch(Exception e)
{
// Log exception
}
finally
{
client.Close();
}
}
That way you are doing a clean close before dispose and it should clean up even if the Modbus protocol throws some kind of exception.
did you play with TcpClient.LingerState Property
defualt setting could cause problems with resetting winsock
check it out
http://msdn.microsoft.com/pl-pl/library/system.net.sockets.tcpclient.lingerstate%28v=vs.110%29.aspx
This is not an answer, but a comment with code. We have this same issue on some of our installed computers, but not all of them. The issue itself is also very intermittent, sometimes going months without happening. I am hoping someone can find an answer. Here is our brute force destroy / reconnect code that does not work:
try
{
try
{
try
{
// Close the stream
var stream = _tcpClient.GetStream();
if (stream != null)
stream.Close();
}
catch { }
try
{
// Close the socket
if (_tcpClient.Client != null)
_tcpClient.Client.Close();
}
catch { }
// Close the client
_tcpClient.Close();
_tcpClient = null;
}
catch { }
if (_device != null)
{
_device.Dispose();
_device = null;
}
}
catch { }
System.Threading.Thread.Sleep(1000);

read-loop from TCP/IP

I need to connect a server (with ip and port) and create a read-loop that will get messages from the server as XML. sometimes there are no messages from the server.
I tried to create a connection (works fine) and read messages, I get the first message from the server and when I'm trying to read another one - it get stuck. I think that maybe there are no messages right now but I need that the loop will continue until there will be messages... it doesn't even go to "catch" or "finally", just do nothing..
public class Connection
{
public Connection()
{
Socket server = null;
try
{
string p = string.Empty;
using (var client = new TcpClient(myIPAddress, myPort))
using (var stream = client.GetStream())
using (var reader = new StreamReader(stream))
{
while (p != null)
{
try
{
p = reader.ReadLine();
}
catch (Exception e)
{
//
}
}
}
}
catch (Exception e)
{
//
}
finally {
server.Close();
}
}
}
The loop is continuing, waiting for data. The issue here seems to be simply that ReadLine() is a blocking call. You mention that there might not be a message yet; well, ReadLine() is going to block until one of two conditions is met:
it can successfully read some data, terminated by a newline (or EOF, i.e. a message without a newline followed by socket closure) - in which case it returns the line of data
no more data is received and the stream is closed, in which case it returns null
So basically, ReadLine() is going to wait until either a message comes in, or the socket is closed. That is simply the behaviour of ReadLine(). If that is problematic, you could work closer to the socket, and check NetworkStream.DataAvailable but: note that only tells you if some data is currently available; it doesn't mean "this is an entire message", nor can it be used to tell if more messages will arrive. The main use of DataAvailable is to decide between sync and async access. Plus if you work close to the socket you'll have to do all your own buffering and encoding/decoding.
It looks to me like ReadLine() is working successfully. The only thing I would do here is re-phrase it a bit:
string line;
while((line = reader.ReadLine()) != null) {
// line is meaningful; do something
}
One last thought: xml is not always trivially split into messages simply on a "per-line" basis. You might want to consider some other form of framing, but that may well mean working closer to the socket, rather than a StreamReader.
You have to wait till data arrives at the stream, you could try using follwing,
if(reader.EndOfStream)
continue;

Memory Management and Exception Handling

I have a simple class that handles the connection being made between a client and server.
To let more than one user communicate with the server at one time each new Client connection is made on a separate thread.
In this class I create two streams that act as the inbound and outbound streams for the client. I create the fields first and then initialise the object in a separate method, simply because the object is used in several other places.
I've come to the point where I want to refactor the code to make it more robust, my first port of call was memory management. I've come to love the using() statement but noticed that I can't really see a way to do implement it due to the way the code is structured.
This means I have a fairly annoying method that is just used for closing the underlying connections and nothing more.
Furthermore, I came to implement exception handling and was curious whether the notion of wrapping the entire code in a method with a try{} statement and then having sequential catch() blocks with the applicable exception types was the best idea.
I hope I explained myself correctly, I'll post a snippet for you to look at.
Thanks!
//Fields
TcpClient tcpClient;
//The thread that will send information to the client
private Thread thrSender;
private StreamReader srReceiver;
private StreamWriter swSender;
private string currentUser;
private string strResponse;
//The constructor of the class takes in a TCP connection
public Connection(TcpClient tcpCon)
{
tcpClient = tcpCon;
//The thread that accepts the client and waits messages
thrSender = new Thread(AcceptClient);
//The thread calls the AcceptClient method
thrSender.Start();
}
private void CloseConnection()
{
//Close the currently open objects
tcpClient.Close();
srReceiver.Close();
swSender.Close();
}
//Occurs when a new client is accepted
private void AcceptClient()
{
srReceiver = new StreamReader(tcpClient.GetStream());
swSender = new StreamWriter(tcpClient.GetStream());
//Read account information from the client
currentUser = srReceiver.ReadLine();
//Examine response from client
if (currentUser != "")
{
//Store the user name in the hash table
if (ChatServer.htUsers.Contains(currentUser) == true)
{
//0 means not connected - Writes error to Client and Server log
swSender.WriteLine("0|This username already exists.");
swSender.Flush();
CloseConnection();
return;
}
//More if/else if/else statements
//...
}
}
You can dispose of the two streams fairly easily within the AcceptClient method by making them local variables since they aren't referenced elsewhere something like this:
private void AcceptClient()
{
using (StreamReader srReceiver = new StreamReader(tcpClient.GetStream()))
{
using (StreamWriter swSender = new StreamWriter(tcpClient.GetStream()))
{
// ...
}
}
}
The tcpClient is more tricky because it is being created on one thread and cleaned up on another. Unless you can change that then perhaps the best option is going to be to implement the cleanup within a try/finally.
private void AcceptClient()
{
try
{
using (StreamReader srReceiver = new StreamReader(tcpClient.GetStream()))
{
using (StreamWriter swSender = new StreamWriter(tcpClient.GetStream()))
{
// ...
}
}
}
finally
{
tcpClient.Dispose();
}
}
The finally clause will get called whether or not the try clause throws an exception.

Best way to keep a pipe open after a remote close

Using this tutorial i came up with the code below. My client is ran frequently. Its activated via clicks and possibly can be launched twice at the same moment in certain circumstance. I am worried one client may close while another client opens which causes the pipe to be closed in that slim few milliseconds. Whats the best way to keep the pipe open?
static public void ThreadStartServer()
{
while (true)
{
using (NamedPipeServerStream pipeStream = new NamedPipeServerStream("mytestpipe"))
{
Console.WriteLine("[Server] Pipe created {0}", pipeStream.GetHashCode());
pipeStream.WaitForConnection();
Console.WriteLine("[Server] Pipe connection established");
using (StreamReader sr = new StreamReader(pipeStream))
{
string temp;
while ((temp = sr.ReadLine()) != null)
{
Console.WriteLine("{0}: {1}", DateTime.Now, temp);
}
}
}
}
Make your pipe server multi-threaded, with one thread dedicated to listening. See these answers:

Categories

Resources