socketstcpnetduino

TCP Sockets and .Net Micro Framework


I'm new to sockets and just can't seem to get my app working. What I want to do is send a log file from the Netduino+2 back to my laptop. The approach I took was to prepend the file size to the byte array before sending. However, I never seem to receive exactly what I send. I realize this is a very common problem with folks who are new to sockets and I've searched high and low to find tips on how to avoid this problem. Maybe this is something unique to micro framework, but I kind of doubt it.

Here is my code. I've got a client app that runs on the N+2 and a console app running on my laptop. The data file I'm retrieving is attached below. This sort of works, but is not delivering the file consistently. Any help you can give me would be appreciated.

Client app running on N+2. When you press the onboard button, it sends the file.

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
using System.IO;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

namespace SocketClient
    {

    public class Program
        {
        static string strDeviceIP = "";
        static string strDeviceSubnet = "";
        static string strDeviceGateway = "";
        static string strDevicePort = "";
        static string strControllerIP = "";

        public static OutputPort opLED = new OutputPort(Pins.GPIO_PIN_D13, false);
        InputPort button = new InputPort(Pins.ONBOARD_SW1, false, Port.ResistorMode.Disabled);

        public static void Main()
            {
            strDeviceIP = "192.168.2.102";
            strDeviceSubnet = "255.255.255.0";
            strDeviceGateway = "192.168.2.2";
            strControllerIP = "192.168.2.222";
            strDevicePort = "9999";
            InterruptPort btn = new InterruptPort(Pins.ONBOARD_SW1, false, 
                              Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeLow);
            btn.OnInterrupt += new NativeEventHandler(ButtonPress);

            while (true)
                {

                }
            }

        public static void ButtonPress(uint data1, uint data2, DateTime time)
            {
            opLED.Write(true);

            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
                    ProtocolType.Tcp);
            IPAddress hostAddress = IPAddress.Parse(strControllerIP);
            IPEndPoint endpoint = new IPEndPoint(hostAddress, Int32.Parse(strDevicePort));

            string fileName = "runlog2.txt";

            // read the file into a byte array
            byte[] data = File.ReadAllBytes(@"SD\" + fileName);
            byte[] sizeinfo = new byte[4];
            byte[] senddata = new byte[4 + data.Length];

            // check to make sure it's not too big
            if (data.Length > 850 * 1024)
                {
                Debug.Print("File too large");
                }

            // convert data.length into a byte array
            sizeinfo[0] = (byte)data.Length;
            sizeinfo[1] = (byte)(data.Length >> 8);
            sizeinfo[2] = (byte)(data.Length >> 16);
            sizeinfo[3] = (byte)(data.Length >> 24);

            // prepend the size into the senddata array
            sizeinfo.CopyTo(senddata, 0);

            // copy read data into the senddata array
            data.CopyTo(senddata, 4);

            // send the data
            socket.Connect(endpoint);
            socket.Send(senddata);
            socket.Close();
            opLED.Write(false);
            }
        }
    }

Here is my server side console app.

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Threading;





namespace SocketConsole
    {
    class Program
        {
        static void Main(string[] args)
            {
            Thread thread1 = new Thread(new ThreadStart(Listener));
            thread1.Start();



            while (true)
                {
                }
            }

       public static void Listener()
            {
            try
                {
                Socket sktMain = new Socket(AddressFamily.InterNetwork, SocketType.Stream, 
                                      ProtocolType.Tcp);
                sktMain.Bind(new IPEndPoint(IPAddress.Parse("192.168.2.222"), 9999));
                sktMain.Listen(10);
                var message = new ArrayList();

                while (true)
                    {
                    // create the client socket
                    using (var client = sktMain.Accept())
                        {
                        //If connected,
                        if (SocketConnected(client, 100))
                            {
                            while (SocketConnected(client, 100))
                                {
                                byte[] sizeinfo = new byte[4];

                                //read the size of the message into sizeinfo
                                int totalread = 0, currentread = 0;
                                currentread = totalread = client.Receive(sizeinfo, 4, 
                                SocketFlags.None);

                                while (totalread < sizeinfo.Length && currentread > 0)
                                    {
                                    currentread = client.Receive(sizeinfo, totalread,
                                 sizeinfo.Length - totalread, SocketFlags.None);
                                    totalread += currentread;
                                    }

                                int messagesize = 0;
                                messagesize |= sizeinfo[0];
                                messagesize |= (((int)sizeinfo[1]) << 8);
                                messagesize |= (((int)sizeinfo[2]) << 16);
                                messagesize |= (((int)sizeinfo[3]) << 24);

                                byte[] data = new byte[messagesize];
                                totalread = 0;
                                currentread = totalread = client.Receive(data, 0, data.Length -
                               totalread, SocketFlags.None);
                                var received = Encoding.UTF8.GetChars(data);

                                int diff = data.Length - totalread;

                                while (totalread < messagesize && currentread > 0)
                                    {
                                    currentread = client.Receive(data, 0, data.Length - totalread,
                                    SocketFlags.None);
                                    totalread += currentread;
                                    for (var i = 0; i < received.Length; i++)
                                        message.Add(received[i]);
                                    }
                                string fName = "runlog.txt";
                                if (File.Exists(fName)) File.Delete(fName);

                                BinaryWriter bWrite = new BinaryWriter(File.Open(fName, 
                             FileMode.Create));
                                bWrite.Write(data);
                                bWrite.Close();
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                Console.WriteLine(ex.Message);
                }
            }

           // socket polling
           static bool SocketConnected(Socket s, int ms)
               {
               return !(s.Poll(ms, SelectMode.SelectRead) & (s.Available == 0));
               }

        }
    }

If I look at the byte array data, after receiving all the data, every byte above 255 has a value of 0. It's as if it stops reading at 255. If I debug.print in the while loop filling "data", I get the following output:

client accepting data
 client.Receive sizeinfo: currentread = 4, totalread = 4
 total message size = 3296
 client.Receive data: currentread = 252, totalread = 252
 client.Receive data: currentread = 256 totalread = 508
 client.Receive data: currentread = 256 totalread = 764
 client.Receive data: currentread = 256 totalread = 1020
 client.Receive data: currentread = 256 totalread = 1276
 client.Receive data: currentread = 256 totalread = 1532
 client.Receive data: currentread = 256 totalread = 1788
 client.Receive data: currentread = 256 totalread = 2044
 client.Receive data: currentread = 256 totalread = 2300
 client.Receive data: currentread = 256 totalread = 2556
 client.Receive data: currentread = 256 totalread = 2812
 client.Receive data: currentread = 256 totalread = 3068
 client.Receive data: currentread = 228 totalread = 3296
 client.Receive data final: currentread = 228 totalread = 3296

So it is accepting 256 bytes each time, but they are all zero. Obviously, I don't understand what's going on:(


Solution

  • In the second while loop, and while calling the Receive method, you are using it this way:

    currentread = client.Receive(data, 0, data.Length - totalread, SocketFlags.None);
    

    The second parameter here denotes : "The location in buffer to store the received data."

    This means that all your read data is actually overwriting all old data.

    You should replace it with the following code:

    currentread = client.Receive(data, totalread, data.Length - totalread, SocketFlags.None);
    

    Because the totalread varaible in your code always holds the total read bytes which also can be used to point to the new location for the new received data.