This turns out to be harder than I expected, due to the fact that the .Net Micro Framework does not include everything from the full framework.
If you try to connect to a host on the network that doesn't exist, or just isn't responding, your thread will lock up until the host responses (which may be never). Although the .Net Framework theoretically handles all of this with no problem, the 4.2 version of the .Net Micro Framework is missing a number of important properties and methods.
According to the documentation the normal way to handle this situation is to set the Blocking socket option to false, then the Connect() method will throw an exception because it can't connect immediately (the TCP connect protocol takes some time). You catch the expection and wait for the connection to be be completed, and if it doesn't complete quick enough then you return an error. No hang.
Unfortunately, the 4.2 .Net Micro Framework is missing the Blocking and Connected properties, and the Send() method does not work as documented. The following code shows how to get around this ... but it's a kludge.
using System.Net.Sockets;
using System.Reflection;
int TIME_PORT = 37;
IPEndPoint iep = new IPEndPoint(
IPAddress.Parse("192.168.3.3"), TIME_PORT);
Socket socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
Type sType = Type.GetType("System.Net.Sockets.Socket");
FieldInfo blockingInfo = sType.GetField("m_fBlocking",
BindingFlags.NonPublic | BindingFlags.Instance);
blockingInfo.SetValue(socket, false);
try {
socket.Connect(iep);
} catch (SocketException se) {
// Ignore this exception, it takes time to complete the connection.
}
This code uses reflection to access the blocking property which is not publicly available to us. It catches the exception during Connect() and ignores it.
The problem is how to we know if the connect completes.?The documentation says that you should get an exception if you call Send() with a zero length and the socket hasn't finished connecting, but it doesn't. If you call Send() with a non-zero length then it hangs whether blocking is true or false. And if you call Receive() it just returns 0 bytes.
The good news is that the SendTimeout property does work. If you set it to 300 the send will wait for 300 milliseconds and then throw an exception (might as well set the ReceiveTimeout value to 300 too).
So add the following code and you should be good to go. There is a slight chance that you'll need to wait a little bit for the connection to complete, or maybe retry the first send a few times before giving up.
socket.SendTimeout = 300;
socket.ReceiveTimeout = 300;
byte[] cmd = new byte[1];
try {
int xx = socket.Send(cmd, 1, SocketFlags.None);
} catch (SocketException se) {
// Unable to send data - probably no connection.
}