I have a TCP client/server app to communicate with a Windows CE device over an ActiveSync connection. Both the client and server utilize Asynchronous sockets (i.e. the Socket.Begin* and Socket.End* functions). When both the client and server are running on my desktop everything functions exactly as expected, but when the client is running on the Windows CE device that's connected over ActiveSync, I always get a SocketException on the ReceiveCallback after calling Socket.Shutdown (when the device is initiating the disconnect). The full exception is:
System.Net.Sockets.SocketException: An error message cannot be displayed because an optional resource assembly containing it cannot be found
at System.Net.Sockets.Socket.ReceiveNoCheck()
at ReceiveAsyncRequest.doRequest()
at AsyncRequest.handleRequest()
at WorkerThread.doWork()
at WorkerThread.doWorkI()
at WorkItem.doWork()
at System.Threading.Timer.ring()
Everything also seems to work correctly if the server (running on the desktop) initiates the disconnect. I have a couple ideas on how to avoid this, including disallowing device initiated disconnects and ignoring all exceptions after initiating a disconnect. However, I'd like to know why this is happening and if there's a better way of handling it.
The Disconnect and ReceiveCallbacks (operationally identical on both the server and client) are:
public bool Disconnect(StateObject state)
{
try{
if(state.isDisconnecting) return false;
state.isDisconnecting = true;
state.sock.Shutdown(SocketShutdown.Both);
//Wait for sending and receiving to complete, but don't wait more than 10 seconds
for(int i=0; i<100 && (state.isSending || state.isReceiving); i++){
System.Threading.Thread.Sleep(100);
}
/* Log the disconnect */
state.sock.Close();
return true;
} catch (Exception e){
/* Log the exception */
return false;
}
}
private void ReceiveCallback(IAsyncResult iar)
{
StateObject state = (StateObject)iar.AsyncState;
try{
//handle the new bytes in the buffer.
int recv = state.sock.EndReceive(iar);
//Handle the buffer, storing it somewhere and verifying complete messages.
if(recv > 0){
//start listening for the next message
state.sock.BeginReceive(state.recvBuffer, 0, StateObject.BUFFER_SIZE, SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
} else {
state.isReceiving = false;
Disconnect(state);
}
} catch (Exception e){
/* Log the exception */
}
}
//For reference, A StateObject looks kinda like this:
public class StateObject
{
public const int BUFFER_SIZE = 1024;
public Socket sock = null;
public bool isSending = false;
public bool isReceiving = false;
public bool isDisconnecting = false;
public byte[] recvBuffer = new byte[BUFFER_SIZE];
public byte[] sendBuffer = new byte[BUFFER_SIZE];
//Other stuff that helps handle the buffers and ensure complete messages,
// even when TCP breaks up packets.
}
It in order to get the actual exception maybe try figure out which library it needs and deploy it?
If a message connot be shown on your device, because the message is not installed on your device. You have to install a netcf.messages.cab. You will find it here:
C:\Program Files (x86)\Microsoft.NET\SDK\CompactFramework\v3.5\WindowsCE\Diagnostics
After installing this CAB-File, run your application again and post the new error you get.
Related
I have implemented C# tcp-ip client (both synchronous & async reading socket).
After each SocketException, I'm automatically reconnecting connection with server.
Then I have tested communication of client with ncat in windows. Here, if I kill ncat, it throws SocketException in C# client and everything works as I imagine.
But then I have tested it with ncat in linux - here communication works OK, but if I kill ncat server (the same settings like at Windows - ncat -l -k -p xxxx), huge amount of empty data (zero B) is received in callback (or waiting on socket in sync version) and no exception is thrown.
One thing is that Windows / Unix version of ncat can have different behavior. But still I need to solve this weird behavior for any version of tcp-ip server.
/* ------------------------------------------------------------------------- */
public void WaitForData()
{
try
{
if (callback == null)
callback = new AsyncCallback(OnDataReceived);
SocketPacket packet = new SocketPacket();
packet.thisSocket = socket;
m_result = socket.BeginReceive
(packet.dataBuffer, 0, 256,
SocketFlags.None, callback, packet);
}
catch (SocketException ex) { ///reconnecting }
}
/* ------------------------------------------------------------------------- */
public class SocketPacket
{
public System.Net.Sockets.Socket thisSocket;
public byte[] dataBuffer = new byte[256];
}
/* ------------------------------------------------------------------------- */
public void OnDataReceived(IAsyncResult asyn)
{
try
{
SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
int iRx = theSockId.thisSocket.EndReceive(asyn);
char[] chars = new char[iRx];
System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
int charLen = d.GetChars(theSockId.dataBuffer, 0, iRx, chars, 0);
string szData = new string(chars);
szData = szData.Replace("\n", String.Empty);
processMessage(szData);
WaitForData();
}
catch (ObjectDisposedException) { }
catch (SocketException ex) { ///reconnecting }
}
Thank you!
Solved
In OnDataReceived callback, I check amount of incoming data, so I do:
if (iRx == 0)
throw new SocketException(Convert.ToInt16(SocketError.HostDown));
TCP receiver can never get the exact status of the remote connection. Killing the process will send FIN (receive is zero) or RST(get exception) depending on the TCP/IP stack implementation. There are other condition where the application are completely unaware of the connection breakage. Suppose if the remote system is forcefully reset or the cable wire is unplugged or the IP address is changed, there is no way you can get to know the connection broken until you send some data. If your application need to know the status of the connection, it can send some dummy data every 1 minute to make sure the connection alive.
I have many printers I am trying to connect to over tcp connections. I am trying to verify that my TcpClient is still connected to update a GUI. I am trying to write to a socket to make sure its still connected. I get no exception even if the cable is unplugged I tried all of the suggestions here MSDN_Fourm
I am receiving the expected exception after I try to check the printer statuses
psudo-code
client is a TCPClient that has been connected previously
private bool FuntionPsudo(){
try{
if(client.Connected){
byte[] buf = new byte[1];
client.Client.Send(buf, 0,0);
client.GetStream().Write(buf,0,0);
if(client.Client.Receive(buf,SocketFlags.Peek)==0)
return false;
return true;
}
}
catch(Exception){
return false;
}
return false;
}
FuntionPsudo returns: true
cable unplugged
FuntionPsudo returns: true
FuntionPsudo returns: true
check printer status
FuntionPsudo returns: false
Thanks in advance for any help on why this might be happening and/or how to fix it
After several failed attempts I realised 'unplug-the-cable' type of connecting detection isn't that easy. At the same time I found that there are a couple of tricks you can do to check if the server has closed the connection, all without needing to send hearbeat kind of messages.
Here is what I came up with that I could say it works most of the time (especially with cable disconnects it's not easy to figure out if connection is still up)
static class SocketUtils
{
public static bool IsConnected(this Socket socket)
{
return IsSocketConnected(socket) && IsNetworkConnected(socket);
}
public static void KeepAlive(this Socket socket, int pollSeconds)
{
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
SetIOControlKeepAlive(socket, (uint)(pollSeconds * 1000), 1);
}
static bool IsNetworkConnected(this Socket socket)
{
try
{
return socket.Send(new byte[0]) == 0;
}
catch (SocketException) { return false; }
}
static bool IsSocketConnected(this Socket socket)
{
try
{
return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0);
}
catch (SocketException) { return false; }
}
static void SetIOControlKeepAlive(Socket socket, uint time, uint interval)
{
var sizeOfUint = Marshal.SizeOf(time);
var inOptionValues = new byte[sizeOfUint * 3];
BitConverter.GetBytes((uint)(time == 0 ? 0UL : 1UL)).CopyTo(inOptionValues, 0);
BitConverter.GetBytes(time).CopyTo(inOptionValues, sizeOfUint);
BitConverter.GetBytes(interval).CopyTo(inOptionValues, sizeOfUint * 2);
socket.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
}
}
Here is how you can use it:
var tcpClient = new TcpClient();
tcpClient.Connect("192.168.2.20", 3000);
// set this to a low value to detect cable disconnects early
tcpClient.Client.KeepAlive(30); // 30 seconds
Console.WriteLine("Connected..");
while (true)
{
Thread.Sleep(500);
Console.WriteLine(tcpClient.Client.IsConnected());
}
I must add that I shamelessly copied some code from Samuel's answer about checking client disconnects and Greg Dean's answer about setting keep-alive on the socket, so some credit should go to them as well ;)
You can only tell whether you are still connected or not by sending something and receiving something back. Just pushing bytes out into the network always works even if they go into a black hole. The Connected property is unreliable and almost all code using it is wrong.
Send something to the printer and receive a reply. Or, create a new connection (which internally will send and receive TCP control packets without data).
When dealing with transport layers like the TCP protocol you need to use it like a 'Walkie-Talkie'. You need to decide when and for how long to talk. In other words the communication breaks down when both parties talk or listen at the same time.
Here is an example from the book C# in a Nutshell:
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
class TcpDemo
{
static void Main()
{
new Thread(Server).Start(); // Run server method concurrently.
Thread.Sleep(500); // Give server time to start.
Client();
}
static void Client()
{
using (TcpClient client = new TcpClient("localhost", 51111 ))
using(NetworkStream n = client.GetStream())
{
BinaryWriter w = new BinaryWriter(n);
w.Write("Hello");
w.Flush();
Console.WriteLine(new BinaryReader(n).ReadString());
}
}
static void Server()
{
TcpListener listener = new TcpListener(IPAddress.Any, 51111);
listener.Start();
using(TcpClient c = listener.AcceptTcpClient())
using(NetworkStream n = c.GetStream())
{
string msg = new BinaryReader(n).ReadString();
BinaryWriter w = new BinaryWriter(n);
w.Write(msg + " right back!");
w.Flush();
}
listener.Stop();
}
}
I have same this propblem for reconnect.
I write server in java and client in c# (unity)
java-java throw exception ok
java-c# : both of them throw exception in some case.
I have the best way for perfomance server
I resolve by the way : write jar client and use ikvm export to dll (copy jar to ikvm/bin). Create library in c# and reference dll + ikvm.core.dll + .../manage/unityEngine.dll ==> copy Cshapr/bin/Debug to UnityProJect/Asset
--> it run ok but speed over 37M to build ðŸ˜
If you want to have a small client --> network with no reconnect 😅
I am troubleshooting an issue on a relatively simple socket application which is listening for status updates from a third party machine. I have set up a TcpListener object to wait for a connection request and then establish the socket to read the data coming in. I get the periodic heartbeat as expected without issue, but whenever there is a sudden change in status the server machine sends out an immediate update which I don't get. The bizarre thing here is that I get the update no problem if I set a breakpoint in the code.
The server itself handles these connections a little strangely and doesn't maintain an open socket connection. when it tries to send data, it opens the connection, sends data, and then closes the connection, which is why I've built this to similarly wait for a connection and close it when the data transfer is done before beginning to listen for another connection request.
private void ListeningThread()
{
bool keep_going = CreateConnection();
CreateTimer();
while (keep_going)
{
try
{
if (m_ThreadShutdownEvent.IsSet)
{
// event was set, so shut down
keep_going = false;
m_Listener.Stop();
bool appshuttingdown = false;
DestroyTimer();
lock (m_Lock)
{
appshuttingdown = m_ApplicationShutDown;
}
if (!appshuttingdown)
{
RunStatusNotification();
}
Connected = false;
}
else
{
if (m_Listener.Pending())
{
Socket socket = m_Listener.AcceptSocket();
if (socket != null)
{
StateObject state = new StateObject();
state.Socket = socket;
try
{
int bytes_read = socket.Receive(state.Buffer, 0, StateObject.BUFFER_SIZE, SocketFlags.None);
DateTime now = DateTime.UtcNow;
if (bytes_read == 14)
{
if (state.Buffer.Count() > 13)
{
int packet = state.Buffer[13];
InterpretRelevantByte(packet, now);
}
}
}
catch (Exception ex)
{
FireUnknownException(ex);
}
finally
{
socket.Close();
}
}
}
}
}
catch (Exception ex)
{
m_Logger.Error(ex);
}
}
}
It's possible that your call to receive gets you some value greater than or less than 14, you should probably add some logic to inspect the data you receive when bytes read is not equal to 14 since in these cases you are discarding what you've read.
int bytes_read = socket.Receive(state.Buffer, 0, StateObject.BUFFER_SIZE, SocketFlags.None);
DateTime now = DateTime.UtcNow;
if (bytes_read == 14)
{
if (state.Buffer.Count() > 13)
{
int packet = state.Buffer[13];
InterpretRelevantByte(packet, now);
}
}
else if (bytes_read > 14)
{
// maybe you received multiple messages in one packet
}
else
{
// maybe there is more data on the way
}
Ok, I've resolved this. Turns out I was closing the socket too soon which led to some weird behavior that, honestly, I don't fully understand, but I do know how I fixed it.
After opening the socket I needed to continue listening for data until receiving a 0 length message which signaled that the server had closed the connection. At that point I could start listening for a new socket connection request. I'm still not sure why I would get the heartbeats only, but everything has been working perfectly since I made the change.
I have written a small UDP client server class in C# that is used to provide comms between a Linux and a Windows machines.
The implementation of the UDP client and server in C# in Windows is a direct rewrite from C++ code I wrote for Linux originally.
I have no problems during run time between Linux machines but there is an intermittent problem that occasionally appears between Linux and Windows link.
Due to the application I need fast, non blocking operation of the UDP socket.
Since one client is Linux the code under C# I had to use some magic of marshalling.
Here is the code:
public bool Connect(string sIPAddr, int portNumber)
{
try
{
if (portNumber > 65535 && portNumber < 0)
{
this._isReady = false;
return this._isReady;
}
this._ipPort = portNumber;
this._ipAddress = IPAddress.Parse(sIPAddr);
IPEndPoint ipep = new IPEndPoint(this._ipAddress, this._ipPort);
this._myUDPClient = new Socket(ipep.Address.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
this._myUDPClient.Blocking = false;
this._myUDPClient.Connect(this._ipAddress, this._ipPort);
this._isReady = true;
return this._isReady;
}
catch (Exception)
{
this._isReady = false;
return this._isReady;
}
}
I use connect on UDP to simplify send and receive calls.
The problem happens when I try and read from the socket.
More code:
public bool NewMessageReceived()
{
try
{
if (this._newMessaageReceived)
{
return this._newMessaageReceived;
}
else
{
_messageBuffer = new byte[65507];
int numBytesRcvd = _myUDPClient.Receive(this._messageBuffer, 65507, SocketFlags.None);
Marshal.Copy(_messageBuffer, 0, _pmessageBuffer, 65507);
if (numBytesRcvd < 0)
{
this._newMessaageReceived = false;
// TODO: Add Socket Error Checking
}
else
{
this._newMessaageReceived = true;
}
Array.Clear(_messageBuffer, 0, _messageBuffer.GetLength(0));
return this._newMessaageReceived;
}
}
catch (Exception e)
{
System.Windows.Forms.MessageBox.Show(e.Message);
return false;
}
}
I have Wireshark running on both machines and I can see that the datagram sent from Linux machine arrives on Windows machine unharmed. However the UDP client Receive call throws and exception saying: "A non-blocking socket operation could not be completed
immediately" which from what I understand is a WSAEWOULDBLOCK error. However I explicitly set blocking option to false.
The sequence of events is the following:
Windows machine sends a datagram on port 2 and listens for acknowledge on port 1. I have a while loop which implements timeout
Code:
DateTime TimeAtStart = new DateTime();
TimeAtStart = DateTime.Now;
TimeSpan TimeOut = new TimeSpan(0,0,0,0,800);
IntPtr RecievedTelPtr = new IntPtr();
bool UnpackingResult;
while (TimeOut > (DateTime.Now - TimeAtStart))
{
if (!NackAckRecieveConnection.GetIsReady())
{
ErrorEventArguements.SetAllHmiNetworkEventArgs(ID, -3, 2);
return (false);
}
if (NackAckRecieveConnection.NewMessageReceived())
{
RecievedTelPtr = NackAckRecieveConnection.GetMessage();
UnpackingResult = UnpackHmiTelegram(RecievedTelPtr, AckNackType);
NackAckRecieveConnection.MessageRetrieved();
return (UnpackingResult);
}
}
//if escape loop return timeout err msg
ErrorEventArguements.SetAllHmiNetworkEventArgs(ID, -4, (AckNackType == 0) ? (1) : (3));
return (false);
I would like to be able to understand the issue and why the problem occurs and how can I fix it as I have fun out of ideas.
Thank you
I'm not answering the question, but I do need to point out something very important:
catch (Exception)
{
this._isReady = false;
return this._isReady;
}
Do NOT hide exceptions like that. When something fails you will have no chance what so ever to try to fix it, since you will never know why something failed. Do use proper exception handling.
Due to the application I need fast, non blocking operation of the UDP socket
That statement is not correct. Non-blocking sockets are not faster, they simply return before the operation has completed.
I do recommend that you switch back to blocking sockets, since you seem to be new to socket programming. Get the application running first, then try to optimize it.
You are setting the socket that you're reading messages from to non-blocking. This instructs the socket to NOT BLOCK if the operation cannot be completed immediately. What this means in practical terms is that if you attempt to read from the socket and there is nothing waiting to be read, the call will not return successfully.
I don't know how MessageReceived is being called, however I would assume that whatever is calling it is not checking that information is actually ready to be read from the socket, prior to the call.
As you're experiencing an intermittent problem, it would suggest that most of the time, the when MessageReceived is being called, there is data to be read from the socket.
If you want to continue to use non-blocking IO, you need to either change your logic, so that it catches the IO exception and retrys after a short delay (if you're sure there's going to be data there), or check to see if there is actually data available to be read from the socket, prior to attempting to perform the read.
One way to check if there is information available on the socket (prior to attempting to read from it) would be to use Socket.Poll. Something like:
if (_myUDPClient.Poll(myTimeoutInMicroSeconds, SelectMode.SelectRead)){
// Try to read the new messsage
} else {
continue; // go back to top of loop and try again
}
You may also need to check for SelectError state, to determine if the socket has a failure. Most of my socket programming has been from C++, so I'm not sure about the .Net specifics.
I've been working on a socket client program in C# and am wondering how to detect when the other end of a socket has disconnected itself "ungracefully" as in a network cable being unplugged or a hard reset.
I have these functions below to access the socket and according to the SO question here and this MSDN article, the best way to check for a disconnected socket is to send a 1-byte message with a length of 0. If an exception is thrown and WSAEWOULDBLOCK is not the error code then the socket is disconnected. I have tried this but after hard reseting the server connection the client will call Send(new byte[1], 0, 0, SocketFlags.None) and return successfully and the Receive() command right afterwards returns the WSAEWOULDBLOCK error.
What gives??
Here's my code below. _socket is set to non-blocking mode:
private int nonBlockRecv(byte[] recvBytes, int offset, int size, SocketFlags sf)
{
int bytesRecv = 0;
while (true)
{
try
{
nonBlockSend(new byte[1], 0, 0, sf);
bytesRecv = _socket.Receive(recvBytes, offset, size, sf);
break;
}
catch (SocketException excp)
{
if (excp.ErrorCode != 10035) // WSAEWOULDBLOCK
throw excp;
}
}
return bytesRecv;
}
private int nonBlockSend(byte[] sendBytes, int offset, int size, SocketFlags sf)
{
int bytesSent = 0;
while (true)
{
try
{
_socket.Send(sendBytes, offset, size, sf);
break;
}
catch (SocketException excp)
{
if (excp.ErrorCode != 10035) // WSAEWOULDBLOCK
throw excp;
}
}
return bytesSent;
}
Edit: This may be beneficial but the server is Windows Mobile device. I read in another thread that different OSs maybe able to send socket close signals when they're dying. Perhaps the Windows Mobile OS does not do this??
If the remote computer gracefully disconnects the session, the
Socket.Receive() method will return with 0 bytes. You must detect that
to know that the remote end has disconnected:
int recv = sock.Receive(data);
if (recv == 0)
{
// Remote client has disconnected.
}
else
{
// Remote client has sent data.
}
Also, even if there SocketException arises you can identify the exception for socket disconnection.
Hope this helps solve your problem.
I know this is late but I came up with a cunning solution for this.
I had to communicate with 3rd party software which expected a carriage return on every command sent, otherwise it ignored it.
During the main phase my client socket was in a loop receiving responses from the 3rd party software. My solution isn't ideal but the basic premise is that I put a receive timeout on the socket so that the loop will try to read for 5 seconds then fall into the catch, then loop again. Before each receive I call my own isconnected method which performs a small write without a carriage return, so it's ignored by the 3rd party software yet will give me a reliable fallover if the network has dropped. All I do if the write fails is throw a LostConnectionException and handle that externally.
If you are writing both server and client, you can quite easily come up with some checkdigit that the other ignores.
This may not be perfect but it's reliable for me.
while (numberOfBytesRead == 0)
{
try
{
IsConnected();
_socket.ReceiveTimeout = 5000;
numberOfBytesRead = _socket.Receive(myReadBuffer, 0, myReadBuffer.Length, SocketFlags.None);
}
catch (Exception e)
{
if (e.GetType() == typeof (LostConnection))
{
Status = SocketStatus.offline;
throw;
}
}
}
and the isconnected method would look something like this
public bool IsConnected(Socket s)
{
try
{
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("test");
s.Send(buffer, 0, buffer.Length, SocketFlags.None);
}
catch (Exception)
{
throw new LostConnection();
}
return s.Connected;
}