A Cerberus TCP Server

Hi! Help me please. The client PC is not connected to the server on Cerberus. Server code:

sing System;
using Microsoft.SPOT;


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

using Socket = System.Net.Sockets.Socket;

namespace GadgeteerApp4
{
    public delegate void DataReceivedEventHandler(object sender, DataReceivedEventArgs e);

    public class SocketServer
    {
        public const int DEFAULT_SERVER_PORT = 8080;
        private Socket socket;
        private int port;

        public event DataReceivedEventHandler DataReceived;

        public SocketServer()
            : this(DEFAULT_SERVER_PORT)
        { }


        public SocketServer(int port)
        {
            this.port = port;
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
     
        }

        public void Start() 
        {
            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, port);
  
            Debug.Print(port.ToString());
            socket.Bind(localEndPoint);
            socket.Listen(Int32.MaxValue);

            new Thread(StartServerInternal).Start();
        }

        private void StartServerInternal()
        {
            while (true)
            {
                // Wait for a request from a client.
                Socket clientSocket = socket.Accept();

                // Process the client request.
                var request = new ProcessClientRequest(this, clientSocket);
                request.Process();
            }
        }

        private void OnDataReceived(DataReceivedEventArgs e)
        {
            if (DataReceived != null)
                DataReceived(this, e);
        }

        private class ProcessClientRequest
        {
            private Socket clientSocket;
            private SocketServer socket;

            public ProcessClientRequest(SocketServer socket, Socket clientSocket)
            {
                this.socket = socket;
                this.clientSocket = clientSocket;
            }

            public void Process()
            {
                // Handle the request in a new thread.
                new Thread(ProcessRequest).Start();
            }

            private void ProcessRequest()
            {
                const int c_microsecondsPerSecond = 1000000;

                using (clientSocket)
                {
                    while (true)
                    {
                        try
                        {
                            if (clientSocket.Poll(5 * c_microsecondsPerSecond, SelectMode.SelectRead))
                            {
                                // If the butter is zero-lenght, the connection has been closed or terminated.
                                if (clientSocket.Available == 0)
                                    break;

                                byte[] buffer = new byte[clientSocket.Available];
                                int bytesRead = clientSocket.Receive(buffer, clientSocket.Available, SocketFlags.None);

                                byte[] data = new byte[bytesRead];
                                buffer.CopyTo(data, 0);

                                DataReceivedEventArgs args = new DataReceivedEventArgs(clientSocket.LocalEndPoint, clientSocket.RemoteEndPoint, data);
                                socket.OnDataReceived(args);

                                if (args.ResponseData != null)
                                    clientSocket.Send(args.ResponseData);

                                if (args.Close)
                                    break;
                            }
                        }
                        catch (Exception)
                        {
                            break;
                        }
                    }
                }
            }
        }
    }    
}

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


namespace GadgeteerApp4
{
    public class DataReceivedEventArgs : EventArgs
    {
        public EndPoint LocalEndPoint { get; private set; }
        public EndPoint RemoteEndPoint { get; private set; }
        public byte[] Data { get; private set; }
        public bool Close { get; set; }
        public byte[] ResponseData { get; set; }

        public DataReceivedEventArgs(EndPoint localEndPoint, EndPoint remoteEndPoint, byte[] data)
        {
            LocalEndPoint = localEndPoint;
            RemoteEndPoint = remoteEndPoint;
            if (data != null)
            {
                Data = new byte[data.Length];
                data.CopyTo(Data, 0);
            }
        }
    }
}

using System;
using System.Collections;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Presentation;
using Microsoft.SPOT.Presentation.Controls;
using Microsoft.SPOT.Presentation.Media;
using Microsoft.SPOT.Presentation.Shapes;
using Microsoft.SPOT.Touch;

using Gadgeteer.Networking;
using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;








namespace GadgeteerApp4
{
    public partial class Program
    {
        void ProgramStarted()
        {
            ethernetENC28.NetworkUp += new GTM.Module.NetworkModule.NetworkEventHandler(ethernet_NetworkUp);
            ethernetENC28.NetworkDown += new GTM.Module.NetworkModule.NetworkEventHandler(ethernet_NetworkDown);
            ethernetENC28.UseDHCP();

            SetupWindow();

            Debug.Print("Program Started");
            Debug.Print("My IP is: " + ethernetENC28.NetworkSettings.IPAddress);
            Debug.Print("My Sub is: " + ethernetENC28.NetworkSettings.SubnetMask);
        }

        private Text txtAddress;
        private Text txtReceivedMessage;

        private void SetupWindow()
        {
             Font MyFont = Resources.GetFont(Resources.FontResources.NinaB);
          //  displayN18.SimpleGraphics.DisplayText("Loading, please wait...",MyFont,GT.Color.Blue,0,0);
    




      
        }

        private void ethernet_NetworkDown(GTM.Module.NetworkModule sender, GTM.Module.NetworkModule.NetworkState state)
        {
            Debug.Print("Network Down!");
        }

        private void ethernet_NetworkUp(GTM.Module.NetworkModule sender, GTM.Module.NetworkModule.NetworkState state)
        {
            Debug.Print("Network Up!");

            txtAddress.TextContent = "IP Address: " + ethernetENC28.NetworkSettings.IPAddress + ", port 8080";
            
            SocketServer server = new SocketServer(8080);
            server.DataReceived += new DataReceivedEventHandler(server_DataReceived);
            server.Start();
        }

        private void server_DataReceived(object sender, DataReceivedEventArgs e)
        {
            string receivedMessage = BytesToString(e.Data);
            txtReceivedMessage.Dispatcher.BeginInvoke(
                delegate(object arg) { 
                    txtReceivedMessage.TextContent = "Received message: " + arg.ToString(); 
                    return null; 
                }, 
                receivedMessage);
                        
            string response = "Response from server for the request '" + receivedMessage + "'";
            e.ResponseData = System.Text.Encoding.UTF8.GetBytes(response);

            if (receivedMessage == "close")
                e.Close = true;
        }

        private string BytesToString(byte[] bytes)
        {
            string str = string.Empty;
            for (int i = 0; i < bytes.Length; ++i)
                str += (char)bytes[i];

            return str;
        }
    }
}

PC client code:

sing System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace ClientMSDN
{
    class Program
    {
        static void Main(string[] args)
        {
            // Data buffer for incoming data.
            byte[] bytes = new byte[1024];

            // Connect to a remote device.
            try
            {
                // Establish the remote endpoint for the socket.
                // This example uses port 8080 on the local computer.
                IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
                IPAddress ipAddress = ipHostInfo.AddressList[0];
                IPAddress ip = IPAddress.Parse("192.168.100.11"); //Плата
               // IPAddress ip = IPAddress.Parse("192.168.0.103"); // ПК
                IPEndPoint remoteEP = new IPEndPoint(ip, 8080);

                // Create a TCP/IP  socket.
                Socket sender = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);

           
                try
                {
                    sender.Connect(remoteEP);

                    Console.WriteLine("Socket connected to {0}",
                        sender.RemoteEndPoint.ToString());

                    // Encode the data string into a byte array.
                    byte[] msg = Encoding.ASCII.GetBytes("This is a test<EOF>");

                    // Send the data through the socket.
                    int bytesSent = sender.Send(msg);

                    // Receive the response from the remote device.
                    int bytesRec = sender.Receive(bytes);
                    Console.WriteLine("Echoed test = {0}",
                        Encoding.ASCII.GetString(bytes, 0, bytesRec));

                    // Release the socket.
                    sender.Shutdown(SocketShutdown.Both);
                    sender.Close();

                }
                catch (ArgumentNullException ane)
                {
                    Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
                }
                catch (SocketException se)
                {
                    Console.WriteLine("SocketException : {0}", se.ToString());
                }
                catch (Exception e)
                {
                    Console.WriteLine("Unexpected exception : {0}", e.ToString());
                }

            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
     
        }
    }
}

When you run the client simply connects to the server. The server does not ping from the command line.
“System.Net.WebException: Unable to connect to the remote server —> System.Net. Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection fail ed because”

Antivirus and firewall are disabled.

@ artmd64 - I would start with the examples on https://www.ghielectronics.com/docs/30/networking to verify you have a working network first.

@ artmd64 -
Hello,

  1. I got your code working with slight modifications of the ProgramStarted method :

void ProgramStarted()
        {
            ethernetENC28.NetworkUp += ethernetENC28_NetworkUp;
            ethernetENC28.NetworkDown += ethernetENC28_NetworkDown;
            if (!ethernetENC28.NetworkInterface.Opened )
            {
                ethernetENC28.NetworkInterface.Open();
            }
            ethernetENC28.NetworkInterface.EnableDhcp();
            ethernetENC28.NetworkInterface.EnableDynamicDns();
            while (ethernetENC28.NetworkInterface.IPAddress == "0.0.0.0")
            {
                Debug.Print("Waiting for DHCP");
                Thread.Sleep(250);
            }
            //SetupWindow();
            Debug.Print("Program Started");
            Debug.Print("My IP is: " + ethernetENC28.NetworkSettings.IPAddress);
            Debug.Print("My Sub is: " + ethernetENC28.NetworkSettings.SubnetMask);
        }

  1. you didn’t instantiate the variables textAddress and txtReceivedMessage:

         private Text txtAddress = new Text();
         private Text txtReceivedMessage = new Text();
        
  1. I’m not sure if the ENC28 module and the N18 module can be used on the Cerberus in the same application.
    Known Issues
    Socket 5 and 6 on the FEZ Cerberus are both marked as S and P (among others) and use the same SPI bus. The 3 main SPI Pins
    and the 3 PWM pins both use the physical pins 7, 8, and 9 on a socket. As a result, when you use SPI or PWM on those
    sockets, neither SPI nor PWM will function on the other socket.

Does anybody know whether and how two SPI Modules can be used on the Cerberus in the same application?

@ artmd64 -
another mistake is in the method Start()


static IPAddress localIpAddress = null;

then in ProgramStarted:

localIpAddress = IPAddress.Parse(ethernetENC28.NetworkSettings.IPAddress);

then

 public void Start() 
        {
            //IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, port);
            IPEndPoint localEndPoint = new IPEndPoint(localIpAddress, port);

            Debug.Print(port.ToString());
            socket.Bind(localEndPoint);
            socket.Listen(Int32.MaxValue);
            new Thread(StartServerInternal).Start();
        }
        // Do not use the Outcommented line



I converted the port to 80, not 8080

Late reply I know - but as I just went through this and was searching for something else and came across this, I thought I’d confirm…

The known issue documented there will NOT cause an issue, but the ENC28 driver exclusively locks the SPI bus so you cannot use ENC28 on socket 5 or 6 and another SPI device on the empty socket 5 or 6.

Hi Brett,
Some time ago I tried to find out how two SPI-Modules can be used on Cerberus in the same application. It works:
https://www.ghielectronics.com/community/codeshare/entry/1037
Kind regards
RoSchmi

I suspect that the reason your scenario works is actually about initialization order more than anything - the ENC28 driver is explicit, it locks the SPI bus in exclusive mode. If anyone comes along after that exclusive request, they’ll get the exception, thrown by the Gadgeteer library, but it seems that if the shared device gets the bus first, the Gadgeteer lib doesn’t complain and will let the two devices work. GHI have made the decision that the SPI bus for the ENC28 is too important to the use of the network that it must be the only SPI device on that bus. This order-specific behavior is actually how I found this - I had an ENC28 along with a Flash module on a Cerb and they were working fine, but when I replaced the flash module with a display the exception started being thrown - and figured out by looking at the code that it was ENC28 that was requesting the bus as exclusive. So, it’s also possible to change the ENC28 driver and change it to use shared SPI (what I am currently testing) but it’s not intended to be used that way - probably the same disclaimer as your example, responsibility is in the user to test/prove nothing is wrong :slight_smile:

I didn’t check thoroughly if both SPI-Modules work together in all conditions, only tested if it works at all. Looking forward to hear what you will find out.

My app is very simple and controlled in it’s use of SPI devices (very sequential), so I know I’ll never have a conflict between the devices, so it may not be a very useful extra data point. I’d like to think that the exclusive access to the SPI port was precautionary, but I honestly cant; so anyone trying this might run into unexpected situations, and you accept the risk :slight_smile: