Pipe is being closed Exception - c#

Sometimes, on some machines often and on some seldom, the clients which are using my program are getting a "pipe is being closed" exception. This happens on the NamedPipeServerStream that is on .WaitForConnection(). After that, the Application totally crashes and releases a windows exception. This happens when a NamedPipeClientStream transfers information to the standalone application.
main Funktionality:
I wrote several Tools (Office Toolbars, a Service, a standalone .net Application, and a litle starter exe) that communicate together with NamedPipes.
The Service runs a NamedPipeServerStream that is always open (in state .WaitForConnection();) and the Standalone Application has a NamedPipeServerStream too.
The Toolbars and starter .exe communicate with the service. The Service then with the Standalone Application.
what kind of problems can release the pipe is being closed Exception?
Is it possible that the server sends information to the Standalone Application but closes the stream to early because the Standalone Application is not ready or something? on each NamedPipeClientStream i do a waitforpipedrain if pipeClient.IsConnected befor i close the pipeclient..
thanks for help
edit: Here an Example of a clientstream
using (NamedPipeClientStream pipeClient =
new NamedPipeClientStream(".", pipename, PipeDirection.Out))
{
// Wait for a client to connect
try
{
pipeClient.Connect(3000);
// send params to the form
using (StreamWriter sw = new StreamWriter(pipeClient))
{
sw.AutoFlush = true;
sw.WriteLine(sendtext);
}
}
// Catch the IOException that is raised if the pipe is
// broken or disconnected.
catch (Exception e)
{
if (sid != "")
{
connections.Remove(conName);
}
eventLog1.WriteEntry("SendText Fehler 1 " + e.Message);
}
finally
{
if (pipeClient.IsConnected)
{
pipeClient.WaitForPipeDrain();
}
pipeClient.Close();
pipeClient.Dispose();
}
Example of an pipeserver (that runs in a seperad thread)
NamedPipeServerStream pipeServer;
PipeSecurity pipe_security = CreateSystemIoPipeSecurity();
do
string pipename = global::TOfficeCenter.Properties.Settings.Default.pipename;
string aText = "";
pipeServer = new NamedPipeServerStream(pipename, PipeDirection.In, ONE_INSTANCE, PipeTransmissionMode.Byte,
PipeOptions.None, IN_BUF_SIZE, OUT_BUF_SIZE, pipe_security);
try
{
// Verbindung zu TOfficeCenter.exe aufbauen
try
{
IsWaiting = true;
pipeServer.WaitForConnection();
IsWaiting = false;
using (StreamReader sr = new StreamReader(pipeServer))
{
string temp;
while ((temp = sr.ReadLine()) != null)
{
aText = aText + temp;
}
}
try
{
if (aText == "")
{
empfang(null);
}
else
{
if (aText != "KillPipe")
{ // XML empfangen
XmlDocumentTC xml = new XmlDocumentTC();
xml.LoadXml(aText);
empfang(xml);
}
}
}
catch (Exception)
{
empfang(null);
}
}
catch
{...........
}
}
catch (Exception e)
{...........
}
} while (running);
pipeServer.Close();

It's possible that i finally found the problem..
I found out that after this code:
using (StreamWriter sw = new StreamWriter(pipeClient))
{
sw.AutoFlush = true;
sw.WriteLine(sendtext);
}
the pipeClient.IsConnected(); returns directly false, so that it never comes to the WaitForPipeDrain. I Now did it like that and hope that the client does not close the connection before the server is finished with reading..
using (StreamWriter sw = new StreamWriter(pipeClient))
{
sw.AutoFlush = true;
sw.WriteLine(sendtext);
pipeClient.WaitForPipeDrain();
}
Do You Think that could have solved the problem? Since i did it, i never got the error on two test-machines. But the Errors anyway happened seldom..

My use is a bit different, but I'll include the server thread in sum as it's mostly being hacked from the MSDN page at present:
MSDN: How to Use Named Pipes
Not sure if the "WaitForPipeToDrain()" is needed for me, but I took it from your code :)
I think the reset of the pipeServer each time is what cleaned up my IOException.
int threadId = Thread.CurrentThread.ManagedThreadId;
bool sentinel = true;
while (sentinel)
{
NamedPipeServerStream pipeServer =
new NamedPipeServerStream("shapspipe", PipeDirection.InOut, 1);
// Wait for a client to connect
pipeServer.WaitForConnection();
Console.WriteLine("Client connected on thread[{0}].", threadId);
try
{
// Read the request from the client. Once the client has
// written to the pipe its security token will be available.
StreamString ss = new StreamString(pipeServer);
// Verify our identity to the connected client using a
// string that the client anticipates.
ss.WriteString("I am the one true server!");
string message = ss.ReadString();
Console.WriteLine("received from client: " + message);
ss.WriteString("echo from server: " + message);
Console.WriteLine("Received from client: {0} on thread[{1}] as user: {2}.",
message, threadId, pipeServer.GetImpersonationUserName());
}
// Catch the IOException that is raised if the pipe is broken
// or disconnected.
catch (IOException e)
{
Console.WriteLine("ERROR: {0}", e.Message);
}
pipeServer.WaitForPipeDrain();
pipeServer.Close();
}

Related

My P2P app freezes when I clicked anything

I am working on my project where I want to make local P2P communication in C# using Sockets and Threads. I am faced with some troubles when I run my code.
I think the problem is inside next while loop
while (true)
{
try
{
TcpListener listener = new TcpListener(IPAddress.Parse(STD_IP), HOST_PORT);
listener.Start();
using (TcpClient client = listener.AcceptTcpClient())
using (NetworkStream nwStream = client.GetStream())
{
Thread listenerThread = new Thread(() =>
{
string message = Receive(nwStream);
updateBoard(message);
});
listenerThread.Start();
string response = stanje;
Send(nwStream, response);
}
}
catch (Exception er)
{
MessageBox.Show("Communication error: \n\n" + er.Message + "\n" + er.StackTrace);
}
}
while (true) is an infinite loop that your posted code has no way of escaping from.

Host a text file on WindowsCE using a web server

Im trying to host a text file which can be viewed via a browser. This server will be running on a WindowsCE machine.
Currently when i try and view the file on my windows 7 machine using internet explorer 9 it works fine.
Once i host it on WindowsCE internet explorer just sits there waiting with the working circle rotating.
If i run a telnet on port 80 to the webserver i can see my text file is returned:
HTTP/1.1 200 OK
Content-Type: text/plain
MyTextFileContents
Below is the complete method. No exceptions are logged and it logs "Finished serving log".
static void launchLogWebServer()
{
new Thread(delegate()
{
LogIt(0, "Starting Log Server");
TcpListener server = new TcpListener(IPAddress.Any, 80);
server.Start();
TcpClient newConn;
while (true)
{
try
{
newConn = server.AcceptTcpClient();
LogIt(0, "Connection Made to Log Server");
NetworkStream stream = newConn.GetStream();
StreamReader sr = new StreamReader(stream);
StreamWriter sw = new StreamWriter(stream);
sw.WriteLine("HTTP/1.1 200 OK");
sw.WriteLine("Content-Type: text/plain");
sw.WriteLine();
String line = null;
while ((line = sr.ReadLine()).Length != 0)
{
}
string text = string.Empty;
LogIt(0, "Reading Log File");
try
{
using (StreamReader logReader = new StreamReader("mylog.log"))
{
text = logReader.ReadToEnd();
logReader.Close();
}
}
catch (Exception ex)
{
LogIt(0, ex.ToString());
text = ex.ToString();
}
LogIt(0, "Completed Reading Log File");
sw.WriteLine(text);
sw.Flush();
newConn.Close();
LogIt(0, "Finished serving log");
}
catch(Exception ex)
{
LogIt(0, ex.ToString());
}
}
}).Start();
}
EDIT: I should also note my WindowsCE is running .NET Compact Framework 2.0
You need to add 'Content-Length' parameter in HTTP header.

Incomplete messages (C# TCP/IP Client)

First of all, I'm absolutely not a network programmer. What I try to do, is a very simple TCP/IP communication between a Java server and a C# client.
Java server:
public void run(){
try {
// Open server socket
_server = new ServerSocket(SERVER_PORT);
_client = _server.accept();
System.out.println("ComInterface: client connected.");
// Wait for a client data output stream
while(true){
// Receive message from client
BufferedReader is =
new BufferedReader(new InputStreamReader(_client.getInputStream()));
msg = is.readLine();
// Process message
if(msg!=null){
System.out.println("ComInterface: Message Received : <" + msg + ">.");
processMessage(msg); // Independant method
}
else{
System.out.println("ComInterface: client closed connection.");
_client.close();
_client = _server.accept();
System.out.println("ComInterface: client connected.");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendMessage(String msg){
try {
// Out stream
DataOutputStream os = new DataOutputStream(_client.getOutputStream());
os.writeBytes((String)(msg+"\n"+(char)13));
os.flush();
System.out.println("ComInterface: Message <" + msg + "> sent");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
And here's the C# client:
public class ComInterface : MonoBehaviour
{
public const String SERVER_IP = "127.0.0.1"; // Localhost
public const int PORT = 1100; // Default port
public const int READ_BUFFER_SIZE = 5000; // 4.8828125 kilobytes
private TcpClient _client;
private ASCIIEncoding _asen;
private byte[] _readBuffer;
private String _msg;
public Boolean connected { get; internal set; } // setter is for internal use only
/**
* Initialize internal variables (buffer, socket...)
*/
public ComInterface()
{
connected = false;
_client = new TcpClient();
_asen = new ASCIIEncoding();
_readBuffer = new Byte[READ_BUFFER_SIZE];
_msg = String.Empty;
}
/**
* Connect to server at SERVER_IP:PORT
* Return true if connection was a success, or false if failure.
*/
public Boolean Connect()
{
try
{
_client.Connect(SERVER_IP, PORT);
connected = true;
Array.Clear(_readBuffer, 0, _readBuffer.Length);
Debug.Log("TCPClient: <Connect> Connected to the server");
// Start an asynchronous read invoking ReceiveComMessage
_client.GetStream().BeginRead(_readBuffer, 0, READ_BUFFER_SIZE, new AsyncCallback(ReceiveComMessage), _client.GetStream());
}
catch (Exception ex)
{
Debug.Log("TCPClient: <Connect> Cannot connect to the server - " + ex.Message);
connected = false;
}
// Return connection state
return connected;
}
/**
* Received a message from Communicator
*/
private void ReceiveComMessage(IAsyncResult ar)
{
int BytesRead;
String msg;
try
{
BytesRead = _client.GetStream().EndRead(ar);
if (BytesRead < 1)
{
// if no bytes were read server has close.
Debug.Log("TCPClient: <ReceiveComMessage> The server has closed (BytesRead<1)");
this.Disconnect();
return;
}
// Convert the byte array the message was saved into,
msg = Encoding.ASCII.GetString(_readBuffer);
Debug.Log("C# Message: \"" + msg + "\""); // Output example in log below
BytesRead = 0;
Array.Clear(_readBuffer, 0, _readBuffer.Length);
// Start a new asynchronous read into readBuffer.
_client.GetStream().BeginRead(_readBuffer, 0, READ_BUFFER_SIZE, new AsyncCallback(ReceiveComMessage), _readBuffer);
}
catch (Exception ex)
{
Debug.Log("TCPClient: <ReceiveComMessage> The server has closed (Exception):" + ex.Message + " see " + ex.StackTrace);
this.Disconnect();
}
The main problem is that all the message are arriving incomplete. Here's the log trace:
C#: Message "{
C#: Message ""sender":"Bob"",
C#: Message ""recipient":",
etc...
Instead of for instance
C#: Message "{"sender":"Bob","recipient":[1,2,3]}"
I'm a bit confused and I'd need some help to resolve this. Thank you very much!
TCP is a stream-oriented connection, not message-oriented. It has no concept of a message. When you write out your serialized string, it only sees a meaningless sequence of bytes. TCP is free to break up that stream up into multiple fragments and they will be received at the client in those fragment-sized chunks. It is up to you to reconstruct the entire message on the other end.
In your scenario, one would typically send a message length prefix. This way, the client first reads the length prefix so it can then know how large the incoming message is supposed to be.
I would seriously consider using something like Google's Protocol Buffers as a good way of declaring your messages and then streaming them with the size prefix option. The nice thing is that you define your set of messages once and then use the available tools to automatically generate C++, Java, C#, etc code from the message definitions. This will help in having a consistent messaging set that works between languages.
A message (any data, I mean), when sent through a socket, is divided into several packets.
When printing each received packet, you don't see your whole message.
You should define an end of message string (something like ".#."). Until you receive this sequence, you keep concatenating the messages you receive.
This is what session protocols (that is, protocols that run on the top of TCP) do.
Hope this helps.
Regards, Calil
Take a look at this example...
Java TCP Server...
import java.net.*;
import java.io.*;
public class TcpServer
{
public static void main(String h[])
{
try
{
ServerSocket serverSocket = new ServerSocket(1100);
Socket socket = serverSocket.accept();
System.out.println("Client Accepted");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("Received: " + bufferedReader.readLine());
PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);
printWriter.println("Hello Theo. Welcome to socket programming.");
} catch (Exception e)
{
System.out.println(e);
}
}
}
C# TCP Client...
using System;
using System.IO;
using System.Net.Sockets;
class Program
{
static void Main(string[] args)
{
try
{
var client = new TcpClient("localhost", 1100);
var stream = client.GetStream();
var streamWriter = new StreamWriter(stream);
streamWriter.WriteLine("My name is Theo");
streamWriter.Flush();
var streamReader = new StreamReader(stream);
Console.WriteLine("Received: " + streamReader.ReadLine());
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.WriteLine("Press a key to continue.");
Console.ReadKey();
}
}

Using ThreadPool.QueueUserWorkItem to open a TcpClient connection and read data in ASP.NET and SignalR

I've read a couple of posts on SignalR and thought for a fun test project that I could create a web application to poll my onkyo receiver for status and display the results in a browser. For an initial test, I was successfully able to send the current time on the server back to the client by using this code in Application_Start:
ThreadPool.QueueUserWorkItem(_ =>
{
dynamic clients = Hub.GetClients<KudzuHub>();
while (true)
{
clients.addMessage(DateTime.Now.ToString());
Thread.Sleep(1000);
}
});
In the client javascript, i have the following code:
// Proxy created on the fly
var kHub = $.connection.kudzuHub;
// Declare a function on the hub so that the server can invoke it
kHub.addMessage = function (message) {
console.log('message added');
$('#messages').append('<li>' + message + '</li>');
};
// start the connection
$.connection.hub.start();
So all of that works fine. Every second, I get a new list item containing the current server date and time.
Now when I add this code to read data from the Onkyo receiver, it breaks: (still in Application_Start)
ThreadPool.QueueUserWorkItem(_ =>
{
dynamic clients = Hub.GetClients<KudzuHub>();
try
{
while (true)
{
string host = ConfigurationManager.AppSettings["receiverIP"].ToString();
int port = Convert.ToInt32(ConfigurationManager.AppSettings["receiverPort"]);
TcpClient tcpClient = new TcpClient(host, port);
NetworkStream clientSockStream = tcpClient.GetStream();
byte[] bytes = new byte[tcpClient.ReceiveBufferSize];
clientSockStream.Read(bytes, 0, (int)tcpClient.ReceiveBufferSize);
tcpClient.Close();
clients.addMessage(System.Text.Encoding.ASCII.GetString(bytes));
Thread.Sleep(50);
}
}
catch (SocketException ex)
{
// do something to handle the error
}
});
I set a break point and stepped through the code. It gets to this line and then returns.
clientSockStream.Read(bytes, 0, (int)tcpClient.ReceiveBufferSize);
It never finishes the rest of the code to send the message to the client. What am I doing wrong?
Thanks.
I would make some structural changes to your loop to allow the receiver time to respond, remove the overhead of retrieving the configuration every 50 milliseconds, and cleanup the open network stream:
ThreadPool.QueueUserWorkItem(_ =>
{
dynamic clients = Hub.GetClients<KudzuHub>();
TcpClient tcpClient = null;
NetworkStream clientSockStream = null;
try
{
string host = ConfigurationManager.AppSettings["receiverIP"].ToString();
int port = Convert.ToInt32(ConfigurationManager.AppSettings["receiverPort"]);
while (true)
{
if (tcpClient == null) {
tcpClient = new TcpClient(host, port);
clientSockStream = tcpClient.GetStream();
}
if (clientSockStream.CanRead) {
byte[] bytes = new byte[tcpClient.ReceiveBufferSize];
try {
clientSockStream.Read(bytes, 0, (int)tcpClient.ReceiveBufferSize);
} catch (Exception ex) {
// Add some debug code here to examine the exception that is thrown
}
tcpClient.Close();
// Closing the client does not automatically close the stream
clientSockStream.Close();
tcpClient = null;
clientSockStream = null;
clients.addMessage(System.Text.Encoding.ASCII.GetString(bytes));
}
Thread.Sleep(50);
}
}
catch (SocketException ex)
{
// do something to handle the error
} finally {
if (tcpClient != null) {
tcpClient.Close();
clientSockStream.Close();
}
}
});

How to test for a broken connection of TCPClient after being connected?

I've been fighting with one problem for a whole 3 days I can't find any solution, please help :)
I work with Visual Studio 2010 and C# language.
I have a device working like a server, that sends some data in a very irregular periods of time (not possible to define any read timeout).
I wrote a TCP client to connect to that server and read data. It works OK, however when something is wrong with the network and server becomes unavailable (e.g. when I plug out the network cable from my computer), it takes about 10 seconds for application to "notice" there is no connection to the server and throw an exception. (I don't know why exactly 10 seconds? Where it's defined? Can I change it?)
I want to react faster - let say after one second after connection broken.
Googling for answer however doesn't provide me any working solution.
The test code is below, I try to make it on 2 threads: one is reading data, the second one is looking for connection status and should alarm me when it's broken. It's not working neither for TCPClient nor Socket class. I've tried to read / write some data with tcpClient.SendTimeout = 100; and stream.WriteTimeout = 100; but it doesn't seem to work.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
namespace TCPClient
{
class Program
{
static volatile bool _continue = true;
static TcpClient tcpClient;
static NetworkStream stream;
static void Main(string[] args)
{
try
{
//client thread - listen from server
Thread tcpListenThread = new Thread(TcpListenThread);
tcpListenThread.Start();
//connection checking thread
Thread keepAliveThread = new Thread(KeepAliveThread);
keepAliveThread.Start();
while (_continue)
{
if (Console.ReadLine() == "q")
{
_continue = false;
}
}
keepAliveThread.Join(2000);
if (keepAliveThread.IsAlive)
{
Console.WriteLine("Thread keepAlive has been aborted...");
keepAliveThread.Abort();
}
tcpListenThread.Join(2000);
if (tcpListenThread.IsAlive)
{
Console.WriteLine("Listen thread has been aborted...");
tcpListenThread.Abort();
}
}
catch (Exception ex)
{
Console.WriteLine("\n" + ex.Message);
}
Console.WriteLine("\nHit any key to quit...");
Console.Read();
}
private static void TcpListenThread()
{
string server = "172.20.30.40";
int port = 3000;
try
{
using (tcpClient = new TcpClient())
{
tcpClient.Connect(server, port);
if (tcpClient.Connected)
Console.WriteLine("Successfully connected to server");
using (stream = tcpClient.GetStream())
{
while (_continue)
{
Byte[] data = new Byte[1024];
Int32 bytes = stream.Read(data, 0, data.Length);
string responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
Console.WriteLine("Received: {0}, responseData);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("Listen thread exception! " + ex.Message);
}
}
private static void KeepAliveThread()
{
while (_continue)
{
if (tcpClient != null)
{
try
{
//...what to put here to check or throw exception when server is not available??...
}
catch (Exception ex)
{
Console.WriteLine("Disconnected...");
}
}
Thread.Sleep(1000); //test for connection every 1000ms
}
}
}
}
Edit:
#carsten's answer: although it looks promising, this solution do not work...
I made the simplest test application for that:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
namespace TCPClientTest
{
class Program
{
static void Main(string[] args)
{
try
{
string server = "172.20.30.40";
int port = 3000;
using (TcpClient tcpClient = new TcpClient())
{
tcpClient.Connect(server, port);
int i = 0;
while (true)
{
// This is how you can determine whether a socket is still connected.
bool blockingState = tcpClient.Client.Blocking;
try
{
byte[] tmp = new byte[1];
tcpClient.Client.Blocking = false;
tcpClient.Client.Send(tmp, 0, 0);
Console.WriteLine("Connected!");
}
catch (SocketException e)
{
// 10035 == WSAEWOULDBLOCK
if (e.NativeErrorCode.Equals(10035))
Console.WriteLine("Still Connected, but the Send would block");
else
{
Console.WriteLine("Disconnected: error code {0}!", e.NativeErrorCode);
}
}
finally
{
tcpClient.Client.Blocking = blockingState;
}
Console.WriteLine("Connected: {0} ({1})", tcpClient.Client.Connected, i++);
Thread.Sleep(1000);
}
}
}
catch (Exception ex)
{
Console.WriteLine("Global exception: {0}", ex.Message);
}
}
}
}
The results are following, it displays:
Connected!
Connected: True
plus my order number every one second. When I disconnect network cable, it takes 8 seconds to start printing:
Disonnected: error code 10054!
Connected: False
so by 8 seconds I'm not aware that the connection is lost. It looks like pinging is the best option here, yet I'll test another solutions.
I think this is a question that often comes around. This might be why MSDN docs really give a good answer to this - see Socket.Connected
Quote from there:
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.
with this sample code:
// .Connect throws an exception if unsuccessful
client.Connect(anEndPoint);
// This is how you can determine whether a socket is still connected.
bool blockingState = client.Blocking;
try
{
byte [] tmp = new byte[1];
client.Blocking = false;
client.Send(tmp, 0, 0);
Console.WriteLine("Connected!");
}
catch (SocketException e)
{
// 10035 == WSAEWOULDBLOCK
if (e.NativeErrorCode.Equals(10035))
Console.WriteLine("Still Connected, but the Send would block");
else
{
Console.WriteLine("Disconnected: error code {0}!", e.NativeErrorCode);
}
}
finally
{
client.Blocking = blockingState;
}
Console.WriteLine("Connected: {0}", client.Connected);
and the straight forward motification for an extension-method:
public static bool IsConnected(this Socket client)
{
// This is how you can determine whether a socket is still connected.
bool blockingState = client.Blocking;
try
{
byte [] tmp = new byte[1];
client.Blocking = false;
client.Send(tmp, 0, 0);
return true;
}
catch (SocketException e)
{
// 10035 == WSAEWOULDBLOCK
if (e.NativeErrorCode.Equals(10035))
return true;
else
{
return false;
}
}
finally
{
client.Blocking = blockingState;
}
}
This is a very old thread, but it's the first SO post that came up when I searched for this question and I found a more useful solution somewhere else, so I thought I'd post a link to it to help others in the future:
https://social.msdn.microsoft.com/Forums/en-US/c857cad5-2eb6-4b6c-b0b5-7f4ce320c5cd/c-how-to-determine-if-a-tcpclient-has-been-disconnected?forum=netfxnetcom&prof=required
ElFenix posted this answer that worked for me:
// Detect if client disconnected
if (tcp.Client.Poll(0, SelectMode.SelectRead))
{
byte[] buff = new byte[1];
if (tcp.Client.Receive(buff, SocketFlags.Peek) == 0)
{
// Client disconnected
bClosed = true;
}
}
Simple answer. You can't. Tcp is made in a way which doesn't allow this. However, the normal way to achieve this is to send ping's with shorter interval than messages. So, say, that whenever you get a message from the server, you start a clock that count down 1 min, then you send a "ping" command (if you haven't received a new message in between). If you don't receive a response to your "ping" within 30 seconds, you conclude that the connection is broken.
Theoretically, you should be able to do this on a package-level (tcp sends ACK which you should be able to check for), but I don't know if that's possible in C#, or any programming language for that matter, or if you need to do that in firmware/hardware.
it will be correct and working if you type the following:
byte[] tmp = new byte[] {0};
...
client.Send(tmp, 1, 0);
...
Just in case anyone else needs something simple and effective.
This is the code I came up with
while (true)
{
string s = null;
DateTime readLag = DateTime.Now;
try
{
s = streamIn.ReadLine();
}
catch (Exception ex)
{
SocketException sockEx = ex.InnerException as SocketException;
if (sockEx != null)
{
OnDebug("(" + sockEx.NativeErrorCode + ") Exception = " + ex);
}
else
{
OnDebug("Not SockEx :" + ex);
}
}
if (enableLog) OnDebug(s);
if (s == null || s == "")
{
if (readLag.AddSeconds(.9) > DateTime.Now)
{
break;
}
}
else
{
CommandParser(s);
}
}
What I got was native error 10035 every time a read failed but would block.
When the connection was trashed, I instantly got a return with no data.
Setting the readLag.AddSeconds() to just below my read timeout would give me a pretty good idea that the time never elapsed, and I got no data. Which should not happen.
Soon as this criteria popped up, I just kick out of the loop and the thread ends.
Hope this helps anyone else out there.
There is a socket option called SO_KEEPALIVE from the oginal unix implemetnation that has the TCP protocol send occasional probes to make sure the other end of the pipe is still listening. It can be set along with how often the probes are set via Socket.IOControl

Categories

Resources