read-loop from TCP/IP - c#

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;

Related

Async await TCP Server for concurrent connection with database calls

I have to write asynchronous TCP Server on to which multiple GPS Devices will be connecting simultaneously (Count :- 1000 Approx) and will push some data of size less than 1 Kb on server, In the response server will send them simple message containing byte received count, The same procedure will happen every 5 Min.
The data received at server is in CSV Format and contains many decimal values, server suppose to process this data and insert the same into database table
After doing lots of Google I decided to go with C#4.5 async and await methods,
This is the first time I am implementing the TCP Server, I believe this is not really the efficient and professional code so any small of small inputs for the same are greatly appreciated. My sample code is as below
// Server starts from Here
public async void Start()
{
IPAddress ipAddre = IPAddress.Parse("192.168.2.5");
TcpListener listener = new TcpListener(ipAddre, _listeningPort);
listener.Start();
while (true)
{
try
{
var tcpClient = await listener.AcceptTcpClientAsync();
HandleConnectionAsync(tcpClient);
}
catch (Exception exp)
{
}
}
}
// Handle the incoming connection and call process data
private async void HandleConnectionAsync(TcpClient tcpClient)
{
try
{
using (var networkStream = tcpClient.GetStream())
using (var reader = new StreamReader(networkStream, Encoding.Default))
using (var writer = new StreamWriter(networkStream))
{
networkStream.ReadTimeout = 5000;
networkStream.WriteTimeout = 5000;
char[] resp = new char[1024];
while (true)
{
var dataFromServer = await reader.ReadAsync(resp, 0, resp.Length);
string dataFromServer1 = new string(resp);
string status = await ProcessDataReceived(dataFromServer1);
if (status.Length != 0)
await writer.WriteAsync(status);
}
}
}
catch (Exception exp){}
}
//Process Data Function
private async Task<string> ProcessDataReceived(string dataFromServer)
{
List<string> values = dataFromServer.Split(',').ToList();
// Do some calculation and rearrange the data
// Create the datatable and insert the data into datatable
using (SqlBulkCopy bulkcopy = new SqlBulkCopy(_dbConn))
{
bulkcopy.WriteToServer(table);
}
return “status”;
}
At present, I have tested it with single GPS Devices and its working for some 10-15 min. than simply crashed and I am very much doubt full about its in the way it will work when there are multiple concurrent connection.
I just want to Make sure whether my basic approach as show in code is in right direction? Am I processing data in correct way or should I suppose to make the use of queue or some other data structure for processing?
Any inputs are greatly appreciable.
The lack of information means that I'm unable to tell whether this is your actual problem, but as far as problems go, this one's a biggy.
So you're not checking if the other end finished. This is indicated by a return value of 0 when calling ReadAsync.
The result value can be less than the number of bytes requested if the number of bytes currently available is less than the requested number, or it can be 0 (zero) if the end of the stream has been reached.
When this condition is detected, you need to get out of the loop, otherwise bad stuff will happen...
while(true)
{
//....
var dataFromServer = await reader.ReadAsync(resp, 0, resp.Length); //bad name!
if(dataFromServer == 0)
{
break;
}
//....
}
As a rule, when you're doing network programming, you need to trap every possible exception and understand what that exception means. Looking at failure in terms of "oh... it crashed" won't get you very far at all. Network stuff fails all the time and you have to understand why it's failing by reading all the diagnostic information you have to hand.

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);

Why is streamreader hooked up to networkstream returning null on ReadLine()?

In the code below I have a StreamReader reading from a network stream. This code normally will run fine for days. I ran into a problem where all of a sudden StreamReader.ReadLine() started returning null.
According to Microsoft documentation StreamReader.ReadLine() will return null when it has reached the end of the input stream. This doesn't make sense to me when the underlying stream is a NetworkStream. Shouldn't ReadLine() just block until the network stream receives data?
This is the first time I ran into this problem and I have not been able to duplicate it. What could cause this?
Context: the application receives CDR records from a phone switch. The phone switch connects to the application and sends plain old text records. After the switch connects it will remain connected and keep sending records for eternity unless something breaks.
private void ProcessClient(TcpClient client)
{
try
{
using (NetworkStream stream = client.GetStream())
{
using (StreamReader reader = new StreamReader(stream))
{
//continue processing while service is on
while (m_RunService & client.Connected)
{
string curLine = reader.ReadLine();
//code here does stuff to string
//will catch any exceptions that have to do with
//processing the string
}
}
}
}
catch (Exception ex)
{
//write to log
}
}
Here is the code that starts the listener:
private void Listen()
{
try
{
while (m_RunService)
{
try
{
m_TcpClient = m_TcpListener.AcceptTcpClient();
//run on same thread, should only ever be 1 cnx at a time
ProcessClient(m_TcpClient);
}
catch (Exception ex)
{
//write to log
}
finally
{
m_TcpClient.Close();
}
}
}
finally
{
m_TcpListener.Stop();
}
}
The StreamReader will block until it receives data or the connection is closed. It sounds like an exception occurred at the server side, it closed the connection, and the client side received no data.
If the NetworkStream does not have data available, the call to ReadLine() will return null because it assumes it has reached the end of the stream.
Try checking NetworkStream.CanRead and NetworkStream.DataAvailable before calling ReadLine. If the connection has not closed, manually block for a time then try your read again.
EDIT
You can check to see if the connection is still open by making a Send or using the underlying Socket:
The Connected property gets the
connection state of the Socket as of
the last I/O operation. When it
returns false, the Socket was either
never connected, or is no longer
connected.
The value of the Connected property
reflects the state of the connection
as of the most recent operation. If
you need to determine the current
state of the connection, make a
nonblocking, zero-byte Send call. If
the call returns successfully or
throws a WAEWOULDBLOCK error code
(10035), then the socket is still
connected; otherwise, the socket is no
longer connected.
That pretty much sounds like the stream has closed. Otherwise yes: it would block. My guess: network #fail

System.IO.Exception: Pipe is broken

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.

Categories

Resources