Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Socket.Connect() block the device


  • Please log in to reply
5 replies to this topic

#1 fvalmeida

fvalmeida

    New Member

  • Members
  • Pip
  • 2 posts

Posted 21 December 2011 - 01:12 PM

Hi, everyone.

I have a N+ with this configuration:

DeviceInfo:
  HAL build info: 4.2.0.0, Netduino Plus (v4.2.0.0 RC3) by Secret Labs LLC
  OEM Product codes (vendor, model, SKU): 34, 177, 4097
  Serial Numbers (module, system):
    00000000000000000000000000000000
    0000000000000000
  Solution Build Info: 4.2.0.0, Netduino Plus (v4.2.0.0 RC3) by Secret Labs LLC
  AppDomains:
  Assemblies:
    mscorlib,4.2.0.0
    Microsoft.SPOT.Native,4.2.0.0
    Microsoft.SPOT.Hardware,4.2.0.0
    Microsoft.SPOT.Net,4.2.0.0
    System,4.2.0.0
    Microsoft.SPOT.Hardware.SerialPort,4.2.0.0
    Microsoft.SPOT.IO,4.2.0.0
    System.IO,4.2.0.0
    Microsoft.SPOT.Hardware.Usb,4.2.0.0
    Microsoft.SPOT.Hardware.PWM,4.2.0.0
    SecretLabs.NETMF.Hardware,4.2.0.0
    SecretLabs.NETMF.Diagnostics,4.2.0.0
    SecretLabs.NETMF.Hardware.NetduinoPlus,4.2.0.0
    Board.THNPD16I16O,1.0.0.0
    Gsiot.Server,1.0.0.0
    Board.THNPD16I16O.Services,1.0.0.0
    Toolbox.NETMF,1.0.0.0
    Board.Contracts,1.0.0.0
    Board.THNPD16I16O.Contracts,1.0.0.0
    Toolbox.NETMF.Hardware,1.0.0.0
    Board.Services,1.0.0.0

Snippet Code:

public static Socket Connect(string host, int port, int timeout)
        {
            // look up host's domain name to find IP address(es)
            IPHostEntry hostEntry = Dns.GetHostEntry(host);
            // extract a returned address
            IPEndPoint remoteEndPoint = new IPEndPoint(hostEntry.AddressList[0], port);

            // connect!
            Debug.Print("connect...");
            var connection = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            connection.Connect(remoteEndPoint);
            connection.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
            connection.SendTimeout = timeout;
            Debug.Print("connected to... " + remoteEndPoint.ToString());
            return connection;
        }

Walkthrough:

--> N+ is with ethernet cable plugged when initialize
--> N+ has a valid ip address
--> The snippet code is invoked with the following parameters: host: 123.123.123.123, port: 80, timeout 5000
--> The host parameters doesn't exist or is unavailable

Sinthom:

--> The program hangs on the connection.Connect(remoteEndPoint); instruction and doesn't throw an exception.

Why?

Thanks in advance.

#2 Valkyrie-MT

Valkyrie-MT

    Advanced Member

  • Members
  • PipPipPip
  • 315 posts
  • LocationIndiana, USA

Posted 21 December 2011 - 03:37 PM

It looks like you're setting the SendTimeout. I don't think that will allow the Connect method to timeout...

connection.SendTimeout = timeout;

Sadly, the connect method does seem to hang if the connection fails. I assume that 123.123.123.123 is an intentionally invalid address with the intent of testing that circumstance.

--> The program hangs on the connection.Connect(remoteEndPoint); instruction and doesn't throw an exception.


The following code is based on memory, and was originally based on ColinR's code here.

Replace the normal socket.Connect(endPoint) with socket.TryConnect(endPoint) and this code:

public static bool TryConnect(this Socket s, EndPoint ep)
{
     bool connected = false;
     new Thread(delegate 
         { 
              try
              {
                   s.Connect(ep);
                   connected = true;
              }
              catch { }

         }).Start();

     int checks = 10;

     while (checks-- > 0 && connected == false) Thread.Sleep(100);

     // if (connected == false) throw new Exception("Failed to connect");
     return connected;
}

Again, hopefully the code is valid as it is done from memory. This is an extension method that gives you a way to connect without blocking for more than 1 second. If you want it to throw an exception when it fails, just uncomment the "if" statement toward the end.

Note: this is an extension method and must be placed in a static class that is in your namespace for it to be in scope when called.

Also Note: if the connect method actually returns an exception we are catching it and ignore it. This is typically a very bad thing to do as we are potentially masking a useful exception.

-Valkyrie-MT

#3 Robert L.

Robert L.

    Advanced Member

  • Members
  • PipPipPip
  • 100 posts

Posted 21 December 2011 - 03:45 PM

public static Socket Connect(string host, int port, int timeout)
        {
            // look up host's domain name to find IP address(es)
            IPHostEntry hostEntry = Dns.GetHostEntry(host);
            // extract a returned address
            IPEndPoint remoteEndPoint = new IPEndPoint(hostEntry.AddressList[0], port);

            // connect!
            Debug.Print("connect...");
            var connection = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            connection.Connect(remoteEndPoint);
            connection.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
            connection.SendTimeout = timeout;
            Debug.Print("connected to... " + remoteEndPoint.ToString());
            return connection;
        }

Walkthrough:

--> N+ is with ethernet cable plugged when initialize
--> N+ has a valid ip address
--> The snippet code is invoked with the following parameters: host: 123.123.123.123, port: 80, timeout 5000
--> The host parameters doesn't exist or is unavailable

Sinthom:

--> The program hangs on the connection.Connect(remoteEndPoint); instruction and doesn't throw an exception.

Why?

Thanks in advance.


I see the program hang on connect() as well as when just creating the socket. Several others have reported this as well. It's an ongoing problem, that I am hoping will be fixed soon with the next release, scheduled for "soon". In my case, the hangs do not happen everytime, which apparently is happening to you. I recomment you move the
            connection.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
            connection.SendTimeout = timeout;
lines to before the connect(), that might help.

#4 fvalmeida

fvalmeida

    New Member

  • Members
  • Pip
  • 2 posts

Posted 21 December 2011 - 05:25 PM

Hi, folks!!! The solution proposed works... I hope, for next release, the Socket.Connect(...) will be with timeout parameter... to avoid this issue :) Thanks people, for reply fast!

#5 baxter

baxter

    Advanced Member

  • Members
  • PipPipPip
  • 415 posts

Posted 21 December 2011 - 06:10 PM

Here are a couple of links that may provide some insight in to the problem, http://www.dotnetsol...2/linger-error/ http://www.dotnetsol...ord-of-warning/ Baxter

#6 Valkyrie-MT

Valkyrie-MT

    Advanced Member

  • Members
  • PipPipPip
  • 315 posts
  • LocationIndiana, USA

Posted 21 December 2011 - 08:57 PM

Here are a couple of links that may provide some insight in to the problem,

http://www.dotnetsol...2/linger-error/

http://www.dotnetsol...ord-of-warning/

Baxter


I've read those before and it's great advice. Those posts are Epic!

Heck, let's just add those options to the code:

    public static bool TryConnect(this Socket s, EndPoint ep)
    {        
        bool connected = false;             
        new Thread(delegate        
            {                               
                try                              
                {
                    // s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.Linger, new byte[] { 0, 0, 0, 0 });                        
                    s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
                    s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, false);
                    s.SendTimeout = 2000;
                    s.ReceiveTimeout = 2000;
                    s.Connect(ep);

                    connected = true;                              
                }                              
                catch { }                 
            }).Start();             
        int checks = 10;                     
        while (checks-- > 0 && connected == false) Thread.Sleep(100);             
        // if (connected == false) throw new Exception("Failed to connect");             
        return connected;
    }

UPDATE: I commented out the line that sets Linger (taked from the Epic blog post) because it never would connect and threw socket exceptions with that set. So, setting linger does more harm than good. I'm not too surprised. That blog post should be taken with a grain of salt because given the age of the post and the hardware that was being used, it was likely the RTIP TCP/IP stack instead of LWIP used on the NetduinoPlus. Note, the other two socket options that remain don't seem to do any harm, so I am leaving them...

-Valkyrie-MT




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.