Main Site Documentation

Issues with network sockets


#1

Hi all,

I’m having problems with network sockets. After about 25 data requests from my pc to the cobra (over the network), the cobra starts throwing exceptions (see below). Can anyone tell me what I might be doing wrong?


using System;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Microsoft.SPOT;

namespace HAMSCobra
{

  #region EventHandler
  public delegate void MessageEventHandler(Object sender, SocketCommunicationEventArgs nea);

  /// <summary>
  /// EventArgs for the SocketCommunicationEventHandler
  /// </summary>
  public class SocketCommunicationEventArgs : EventArgs
  {
    private string _receivedMessage;
    public SocketCommunicationEventArgs(string receivedMessage)
    {
      _receivedMessage = receivedMessage;
    }
    public string ReceivedMessage
    {
      get { return _receivedMessage; }
    }
  }
  #endregion

  #region CommunicationHandler


  class SocketCommunicationHandler
  {
    private string data = null;
    private static byte[] bytes = null;
    private static int _clientPort;
    private static int _listenPort;
    private static IPAddress _ipAddress = IPAddress.Parse("10.0.10.123");
    private static IPAddress _domoticaServerIP = IPAddress.Parse("10.0.10.65");

    private const char end = ';';
    private static bool started = false;
    private int x = 1;

    private Socket sListener = null;
    private Socket sHandler;

    public event MessageEventHandler MessageEvent;
    public void onMessageEvent(string news)
    {
      if (MessageEvent != null)
      {
        var scea = new SocketCommunicationEventArgs(news);
        MessageEvent(this, scea);
      }
    }

    /// <summary>
    /// Start the SocketCommunicationHandler Thread
    /// </summary>
    /// <param name="ClientPort">Port used to send message to</param>
    /// <param name="ListenPort">Port used to listen for incomming messages</param>
    public SocketCommunicationHandler(int clientPort = 9999, int listenPort = 9998)
    {
      _clientPort = clientPort;
      _listenPort = listenPort;

      if (!started)
      {
        new Thread(StartListeningServer).Start();
        new Thread(StartListening).Start();
        started = true;
      }
    }

    private void StartListeningServer()
    {
      sListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
      IPEndPoint localEndPoint = new IPEndPoint(_ipAddress, _listenPort);
      sListener.Bind(localEndPoint);
      sListener.Listen(10);
    }

    /// <summary>
    /// Start listening for incomming socket messages
    /// </summary>
    private void StartListening()
    {
      try
      {
        while (true)
        {
          try
          {
            using (sHandler = sListener.Accept())
            {
              data = null;
              bytes = new Byte[1024];
              while (true)
              {
                int bytesRec = sHandler.Receive(bytes);
                data = new string(Encoding.UTF8.GetChars(bytes));
                // Look for the end of the message (must end with ;)
                if (data.IndexOf(end) > -1)
                {
                  break;
                }
              }
              // Fire and event containing the received message
              Debug.Print("Text received : " + x + " --> " + data);
              x++;
              onMessageEvent(data);
            }
          }
          catch (SocketException e)
          {
            Debug.Print("!!!!!!!! sHandler Error !!!!!!!!");
            Debug.Print(e.Message.ToString());
          }
          finally
          {
            bytes = null;
            sHandler.Close();
            sHandler = null;
          }
        }
      }
      catch (SocketException e)
      {
        Debug.Print("!!!!!!!!!!!!!!!! StarListening Socket Error !!!!!!!!!!!!!!!");
        Debug.Print(e.Message.ToString());
      }
    }



    /// <summary>
    /// Send a message to the other side
    /// </summary>
    /// <param name="msg">The message to send</param>
    public bool send(string msg)
    {
      IPEndPoint hostep = new IPEndPoint(_domoticaServerIP, _clientPort);

      using (Socket sSender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
      {
        try
        {
          sSender.Connect(hostep);
        }
        catch (SocketException z)
        {
          Debug.Print("Problem connecting to host");
          Debug.Print(z.Message.ToString());
          sSender.Close();
          return false;
        }
        try
        {
          byte[] buf = Encoding.UTF8.GetBytes(msg.Length.ToString() + "," + DateTime.Now.ToString() + "," + msg + ";");

          sSender.Send(buf, 0, buf.Length, SocketFlags.None);
        }
        catch (SocketException x)
        {
          Debug.Print("Problem sending data");
          Debug.Print(x.Message.ToString());
          sSender.Close();
          return false;
        }
        sSender.Close();
        return true;
      }
    }
  }
  #endregion

}

the error after 25 attempts:


Event received: temp;
Text received : 24 --> temp;
Event received: temp;
Text received : 25 --> temp;
Event received: temp;
    #### Exception System.Net.Sockets.SocketException - CLR_E_FAIL (4) ####
    #### Message: 
    #### Microsoft.SPOT.Net.SocketNative::socket [IP: 0000] ####
    #### System.Net.Sockets.Socket::.ctor [IP: 001f] ####
    #### HAMSCobra.SocketCommunicationHandler::send [IP: 0011] ####
    #### HAMSCobra.SocketMessageActions::.ctor [IP: 009d] ####
    #### HAMSCobra.Program::sch_MessageEvent [IP: 0016] ####
    #### HAMSCobra.SocketCommunicationHandler::onMessageEvent [IP: 001b] ####
    #### HAMSCobra.SocketCommunicationHandler::StartListening [IP: 00a5] ####
    #### SocketException ErrorCode = 10024
    #### SocketException ErrorCode = 10024
A first chance exception of type 'System.Net.Sockets.SocketException' occurred in Microsoft.SPOT.Net.dll
    #### SocketException ErrorCode = 10024
    #### SocketException ErrorCode = 10024
!!!!!!!! sHandler Error !!!!!!!!
Exception was thrown: System.Net.Sockets.SocketException
Text received : 26 --> temp;
Event received: temp;
    #### Exception System.Net.Sockets.SocketException - CLR_E_FAIL (4) ####
    #### Message: 
    #### Microsoft.SPOT.Net.SocketNative::socket [IP: 0000] ####
    #### System.Net.Sockets.Socket::.ctor [IP: 001f] ####
    #### HAMSCobra.SocketCommunicationHandler::send [IP: 0011] ####
    #### HAMSCobra.SocketMessageActions::.ctor [IP: 009d] ####
    #### HAMSCobra.Program::sch_MessageEvent [IP: 0016] ####
    #### HAMSCobra.SocketCommunicationHandler::onMessageEvent [IP: 001b] ####
    #### HAMSCobra.SocketCommunicationHandler::StartListening [IP: 00a5] ####
    #### SocketException ErrorCode = 10024
    #### SocketException ErrorCode = 10024
A first chance exception of type 'System.Net.Sockets.SocketException' occurred in Microsoft.SPOT.Net.dll
    #### SocketException ErrorCode = 10024
    #### SocketException ErrorCode = 10024
!!!!!!!! sHandler Error !!!!!!!!
Exception was thrown: System.Net.Sockets.SocketException

means too many sockets open though in my finally block I’m closing the socket. I read somewhere that this can be caused by the GC who didn’t had to time to clean up the sockets yet. My polling happens every 5 secs.


#2

It is not the GC, it is set in the TCP/IP stack. It keeps the socket open after you closing the socket waiting for finalizing all transactions.

you can for close the socket by this

clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, -2);   

I did not fully understand your code, but do you close every socket after your are done with it?

Also the number 25 doesn’t make sense for me, FEZ Cobra can accept a maximum of 128 sockets at the same time.


#3

I guess we don’t see the whole picture from the example. His send() method “eats” one socket too, although it is closed at the end as well…


#4

What i’m trying (and succeeded) to do is have a threaded tcp server that listens on a specific port, and reply to incoming messages.
The issue that i’m running into is that after 25 connections i get the above mentioned error, and the only way to get rid of it is to reset the cobra.

I’ll post a new code example with the bare minimum needed to get this running.

Stay tuned please :wink:


#5

Ok, I’m still having issues with networking on the Cobra.
Below is the code that is running on the cobra:


  public class SocketServer
  {
    private int i = 0;
    private int y = 0;
    private IPAddress _ipAddress = IPAddress.Any;
    private IPEndPoint cobraIPEndPoint;
    private Socket cobraListenSocket;
    private Socket clientConnectionSocket;

    public SocketServer()
    {
      try
      {
        Thread listenSocketThread = new Thread(new ThreadStart(ListenSocketConnection));
        listenSocketThread.Start();
      }
      catch (Exception ee)
      {
        Debug.Print(ee.Message);
      }
    }

    private void ListenSocketConnection()
    {
      cobraIPEndPoint = new IPEndPoint(_ipAddress, 9998);
      cobraListenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
      cobraListenSocket.Bind(cobraIPEndPoint);
      cobraListenSocket.Listen(50);

      while (true)
      {
        try
        {
          Thread acceptClientConnectionThread = new Thread(new ThreadStart(AcceptClientConnection));
          acceptClientConnectionThread.Start();
        }
        catch (Exception ee)
        {
          Debug.Print(ee.Message);
        }
      }
    }

    private void AcceptClientConnection()
    {
      clientConnectionSocket = cobraListenSocket.Accept();
      Byte[] receiveBuffer = new Byte[1024];
      NetworkStream clientStream = new NetworkStream(clientConnectionSocket);
      while ((i = clientStream.Read(receiveBuffer, 0, receiveBuffer.Length)) != 0)
      {
        string recMessage = new string(Encoding.UTF8.GetChars(receiveBuffer));
        Debug.Print("Received : " + i + " : " + y + " : " + recMessage);
        byte[] transmitBuffer = Encoding.UTF8.GetBytes("I got your data " + y);
        clientStream.Write(transmitBuffer, 0, transmitBuffer.Length);
        Debug.Print("Transmitted: " + new string(Encoding.UTF8.GetChars(transmitBuffer)));
        y++;
        receiveBuffer = new Byte[1024];
        clientConnectionSocket.Close();
        clientConnectionSocket = cobraListenSocket.Accept();
      }
    }
  }

and is started like this:


  public class Program
  {
    static SocketServer socketServer;
    public static void Main()
    {
      socketServer = new SocketServer();
      Thread.Sleep(Timeout.Infinite);
    }

  }

Then i made a test client (console app) which sends 500 requests to the cobra (by opening and closing the socket each time). Code:


  class Program
  {
    static IPEndPoint ip = new IPEndPoint(IPAddress.Parse("10.0.10.123"), 9998);
    static Socket server;

    static void Main(string[] args)
    {
      Console.WriteLine("Sending 500 requests to server every 2 secs");

      for (int x = 0; x < 500; x++)
      {
        try
        {
          server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
          server.Connect(ip);
        }
        catch (SocketException e)
        {
          Console.WriteLine("Unable to connect to server.");
          return;
        }
        server.Send(Encoding.ASCII.GetBytes("Socket Query " + x + ";"));
        byte[] data = new byte[1024];
        int receivedDataLength = server.Receive(data);
        string stringData = Encoding.ASCII.GetString(data, 0, receivedDataLength);
        Console.WriteLine(x + " Got back: " + stringData);
        server.Close();
        Thread.Sleep(1000);
      }
      Thread.Sleep(Timeout.Infinite);
    }
  }

after about 85 requests I get:


    #### Exception System.IO.IOException - 0x00000000 (2060) ####
    #### Message: 
    #### System.Net.Sockets.NetworkStream::Read [IP: 0017] ####
    #### CobraSocketTest2.SocketServer::AcceptClientConnection [IP: 00ce] ####
    #### SocketException ErrorCode = 10035
An unhandled exception of type 'System.Net.Sockets.SocketException' occurred in Microsoft.SPOT.Net.dll

Can anyone tell me what I’m doing wrong?

The goal is to have network communication between a windows app and the cobra. I prefer to close the sockets each time as I can not predict how often messages will be transmitted.

Any help highly appreciated.


#6

Sockets “linger” for few seconds after they are closed so if you try to open/close sockets quickly then you will end up with no free sockets…they are all closed but they are all in linger state.

You can use the code that was provided by our support to disable the linger feature. See Joe’s answer above.


#7

Gus,
with that option set i can get to 100 requests instead of 85 and the same error pops up.

I placed the option like this:


    private void AcceptClientConnection()
    {
      clientConnectionSocket = cobraListenSocket.Accept();
      clientConnectionSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, -2);
      Byte[] receiveBuffer = new Byte[1024];
      NetworkStream clientStream = new NetworkStream(clientConnectionSocket);
      while ((i = clientStream.Read(receiveBuffer, 0, receiveBuffer.Length)) != 0)
      {
        string recMessage = new string(Encoding.UTF8.GetChars(receiveBuffer));
        Debug.Print("Received : " + i + " : " + y + " : " + recMessage);
        byte[] transmitBuffer = Encoding.UTF8.GetBytes("I got your data " + y);
        clientStream.Write(transmitBuffer, 0, transmitBuffer.Length);
        Debug.Print("Transmitted: " + new string(Encoding.UTF8.GetChars(transmitBuffer)));
        y++;
        receiveBuffer = new Byte[1024];
        clientConnectionSocket.Close();
        clientConnectionSocket = cobraListenSocket.Accept();
        clientConnectionSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, -2);
      }
    }

Any other suggestions?


#8

Why you are accepting connections inside a while loop?

Take a look at the example provided by Microsoft, TCP server. Can you get that example to fail?


#9

I will try if you tell me where i can find that example.


#10

“My Documents”


#11

C:\Users\Yourname\Documents\Microsoft .NET Micro Framework 4.1\Samples

Assuming Windows 7/Vista


#12

Gus,

I tried the MS tcp server example, and it behaves slightly different. Instead of the debugger window of the cobra showing the error, now it just quits my tcp client with the following error: (I only changed the string s to contain “Server reply” instead of the html string in the tcp server example)


A first chance exception of type 'System.Net.Sockets.SocketException' occurred in System.dll
The thread 'vshost.RunParkingWindow' (0x12f8) has exited with code 0 (0x0).
The thread '<No Name>' (0x1080) has exited with code 0 (0x0).
The program '[4176] ConsoleSocketClientTest.vshost.exe: Managed (v4.0.30319)' has exited with code 0 (0x0).

No error is shown in the debugger window of the cobra. Restarting the client results in immediate closure of the client with again the same error as above.
Only resetting the cobra allows the tcp client to connect again.
It happens after 100-128 connections (random).


#13

Yes 128 sockets, that is normal. Now add the code to disable linger and it should work fine


#14

I now tested with the linger line in place, and it successfully ran the 500 connections test.

I will continue to play around and see how far I get.


#15

Is linger disabling supported on W5100 sockets? I know that Get/SetSocketOption are not supported in general on W5100 socket implementation. I have a similar issue in my HttpListener.


#16

Cool Architect (well, kinda), thought i was the only one experiencing this ;D


#17

Not supported since the TCP/IP stack is inside the W5100 chip not FEZ but we can look at the chip datasheet and see if it has some control over that.


#18

Alright, thanks. Back to the drawing board. :o


#19

while (true)
      {
        try
        {
          Thread acceptClientConnectionThread = new Thread(new ThreadStart(AcceptClientConnection));
          acceptClientConnectionThread.Start();
        }
        catch (Exception ee)
        {
          Debug.Print(ee.Message);
        }
      }

I might be wrong, but aren’t you starting threads forever with the above code? (Even without a client connecting)