2

I'm facing a problem of stop the socket.connect() function. Sometimes the physical link between my local machine and the remote machine might be good, but due to some reason, the remote endpoint cannot be accessed, maybe a firewall or the port on the remote machine is closed. In such cases, the socket.connection() function will be stuck there and waits for an infinite long time...Even the firewall is disabled later, the function will still stuck there forever.

So I tried to find a way to stop the socket.connect() when faces the above situations.

The thing is I'm using a .net micro framework in which I dont have timeout mechanism or task or socket.beginconnect();

I'm trying making the socket.connect() itself a thread and tried to abort() it after 2 seconds if (!thread.join(2000)). However, I dont quite understand the abort() function and i've heard its an unwise way to do so and it does not work afterall.

Now i dont know what to do about it? can anyone help? thx a lot

 main function
 {
 m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//Set up socket    
 remoteEndPoint = new IPEndPoint(IPAddress.Parse(IP_add), 30000);
 m_socket.Connect(remoteEndPoint);
 myThread.Start();
        if (!myThread.Join(2000))
         {
          Debug.Print(myThread.ThreadState.ToString());
          myThread.abort();                       
         }
 }

 private static void socket_connect()
    {
        m_socket.Connect(remoteEndPoint);//Connect to remote device  
    }
henryyao
  • 1,758
  • 6
  • 23
  • 37
  • Yes, abort is unwise. Don't use it until you understand it (you don't understand it right now but are using it). – usr Jan 31 '13 at 21:27
  • @usr ya, i know but it seems i dont have other option – henryyao Jan 31 '13 at 21:37
  • Instead of using a thread for connect you can create a thread for timeout. Then you can leave second thread without any code like abort or interrupt. It will be cleaned automatically. – Soroush Falahati Jan 31 '13 at 21:40
  • And also. Thread.Abort was unsafe in .net 1.1 and .net 2 days. It is not much safer. – Soroush Falahati Jan 31 '13 at 21:41
  • 1
    And it still doesn't work because Abort cannot abort IO. It cannot not help you. Dispose the socket after you detect a timeout. – usr Jan 31 '13 at 21:42
  • @SoroushFalahati I dont get it. Could you show me the code plz? – henryyao Jan 31 '13 at 21:51
  • @henryyao tested what i said before and no success. So I wrote an other code using non-blocking connection and it must solve your problem. Just check my answer. – Soroush Falahati Jan 31 '13 at 22:18

2 Answers2

3

It was proposed to have the Connect call timeout by busy-waiting. I strongly disagree with a) that philosophy and b) the proposition that WinSock does not offer a better way to solve this common problem.

Here is a better solution:

        using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
        {
            Task.Factory.StartNew(() =>
                {
                    Thread.Sleep(1000);
                    socket.Close();
                });
            try
            {
                socket.Connect("192.168.2.123", 1234);
            }
            catch (SocketException sex)
            {
                if (sex.ErrorCode == 10038)
                    Console.WriteLine("Timeout");
                else
                    throw;
            }
        }

You detect the timeout yourself and close the socket. This program takes about 1sec to run so the timeout mechanism worked.

Note, that the above code is demo code and should use a timer and be made race-free.

What's wrong about busy-waiting?

  • Bad to maintain
  • Introduces latency
  • Perf-problem in case of many sockets. Totally non-starter on server-systems
  • On clients the CPU cannot power-down and you burn your battery
usr
  • 168,620
  • 35
  • 240
  • 369
  • 1
    This is the correct answer as it's the only way to do it in .net micro framework. This is because it doesn't support async operations on sockets. As a Task replacment use `new Thread(() => { Thread.Sleep(1000); theSocket.Close(); }).Start();` – Nico Dec 04 '15 at 17:26
  • @Nico even with async operations the code looks the same. It's not a good idea to simply abandon async IO because it continues to consume resource, network traffic and ports. – usr Dec 04 '15 at 17:28
  • I didn't say its a good idea but the only way to do it in .net micro framework which OP's question is based on. – Nico Dec 04 '15 at 17:31
0

If your framework support non-blocking connections you can try this code. I wrote this for .net 4 in Win7.

        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        Console.WriteLine("Trying to connect");
        socket.Blocking = false;
        try
        {
            socket.Connect("8.8.8.8", 5050);
        }
        catch (Exception ex)
        {
            if (ex is SocketException) && ((SocketException)ex).ErrorCode == 10035) // There is a socket problem and this problem is because of being in non-blocking mode? Then this is just a warning
            {
                // Waiting for connection
                int time = 0;
                while (time < 1000) // If it was lower than 1 second
                {
                    // Do what you want
                    if (socket.Connected) // If connected then break
                        break;
                    System.Threading.Thread.Sleep(50); // Wait 50milisec
                    time += 50;
                }
            }
            else
            {
                Console.WriteLine("Failed");
            }
        }

        if (!socket.Connected)
            Console.WriteLine("Aborted");
        else
            Console.WriteLine("Connected");
Soroush Falahati
  • 2,196
  • 1
  • 27
  • 38
  • How do you set the timeout to a certain value? Is there a way around busy-waiting? – usr Jan 31 '13 at 23:08
  • 2
    busy waiting is a valid technique. +1... of course you must understand that by default it wont sleep 10 ms but rater 40-50.. ja? ;) – Boppity Bop Jan 31 '13 at 23:15
  • well, unfortunately, my platform does not support the non-blocking connections. but thanks anyway. – henryyao Feb 01 '13 at 04:23
  • @usr Busy waiting is only way you can do something with non-blocking sockets when you have one socket. And about time out you need to change this line: while (time < 1000) to any millisecond number you want. – Soroush Falahati Feb 01 '13 at 09:59