Need to transfert a file over tcp any advice?

Hello

I would like to transfer files between a pc and an EMX module using tcp.

I succeed to see some data but have a lot of troubles to obtain something that is reliable. And I need to rewrite my code.

Files are about 200kB to 400kB.

Do you have any advice?

I just got done slapping on HTTPGet to my NETMF PC. Downloading files over HTTP is quite reliable and setting up a simple IIS to hold your files is easy too.

@ leforban - TCP is reliable. please prepare a short program which shows the problem you are seeing.

First, who is the client the pc or the EMX?

I know that tcp is reliable. However for example, I am supposed to receive 154910 bytes from the PC (server). The emx (client) receive first the size of requested data:



byte[] r = COM_PC.tcpread_raw();
                string sreq_size = BitConverter.Bytes2S(r);
                int req_size = int.Parse(sreq_size);
                DebugInfo.Print("Sie of data that will be send by the PC: " + req_size);

then the code loop until the file is received (or at least it should)


cur_raw = COM_PC.tcpread_raw();
                Debug.Print("ms.length" + ms.Length);
                while (ms.Position < req_size)
                {
                    Debug.Print("Writing" + cur_raw.Length +"bytes");
                    ms.Write(cur_raw, 0, cur_raw.Length);
                    Debug.Print(ms.Position.ToString());
                    cur_raw = COM_PC.tcpread_raw();
                }

But the problem is the following:
the output windows print:
ms.length0
Writing32180bytes
32180
Writing30720bytes
62900
Writing30132bytes
93032
Writing28672bytes
121704
Writing27212bytes
148916
Writing26334bytes
175250

Why there is more data than expecting?

On the pc side, data are send by chunk of 1024 bytes.

I dump then the memory stream into a file stream and I observe the file but there’s some null character inside… Any reason??? I would understant if I was reading a fixed amount of bytes on the socket… but:

Read Raw is:

public byte[] tcpread_raw()
        {
            byte[] buff = new byte[0];
            Eth.tcpread(ref buff);
            return (buff);
        }

and the tcp read method is:

  public static void tcpread(ref byte[] bin)
        {
            if(tcpsocket.Poll(1000000,SelectMode.SelectRead))
            {
                bin = new byte[tcpsocket.Available];
                tcpsocket.Receive(bin,bin.Length,SocketFlags.None);
            }
        }

Any help wll be appreciated

Hello andre.m

I am seeing tcp stream with wireshark. Size of frame are not 1024 (1460,588,878,1176…)
Data seems to be ok on wireshark but Null characters are inserted in the memorystream.

These null characters appears at the end of each frame. I do not understand why…

I would check what Receive method returns and use that as the number of bytes to write.

Hello Architect, this is what the code is supposed to do:

if(tcpsocket.Poll(1000000,SelectMode.SelectRead))
            {
                bin = new byte[tcpsocket.Available];
                tcpsocket.Receive(bin,bin.Length,SocketFlags.None);
            }

the receive method is supposed to fill the bin (byte array) with the available number of bytes received on the socket.

Maybe there’s something wrong here… I will check what there’s in the byte array just after receiving the tcp frame;

I understand that you request the Receive method to get all “available” bytes. But you should rely on the return value of The Receive methods since that is the indicator of valid bytes in your buffer.

It is possible to receive less then what you have asked and that would cause extra bytes written into your stream.

@ andre.m I am talking about Receive method. It returns the number of bytes that was “received” it can be the same as socket.Available.

@ Architect - you are absolute right. I had the very same issue and using the returned byte count fixed it. I think passing a zero length buff gets allocated some arbtrary size and therefore it may be larger than than the actual bytes read.

Then you have been lucky. Because nowhere in documentation on Receive method it says that you will get exactly socket.Available number of bytes. But it does say that Receive will return the number of bytes you have successfully received.

So if I understand properly, available return the total number of bytes available.

Let’s say that it returns 15480 bytes. If I create a byte array bin of size 15480 and call receive… maybe I wil have only a thousand of bytes read and the rest of bin will be null_padded.

Am I correct?

Yes.

Available tells how much is available at the moment, but there is no guarantee that Receive will return all of that.

This can be the reason… I modify the code and will let U know!

@ andre.m - I saw the same thing but I used the recieve timeout at the end to stop the receive. I tried the sleep but it slowed the transfer down too much having a sleep every read.

@ andre.m - Sounds good.

I have made modification in my code to adapt the size of buffer according to the size of valid data received.

public static int tcpread(ref byte[] bin)
        {
            if (tcpsocket.Poll(1000000, SelectMode.SelectRead))
            {
                Debug.Print("Available bytes on the socket" + tcpsocket.Available);
                bin = new byte[(tcpsocket.Available > 1024) ? 1024 : tcpsocket.Available];
                return tcpsocket.Receive(bin);
            }
            else return 0;
        }

The problem is that at one moment the socket.available return 0 whereas there’s still data that are send from the PC.

It seems that as andre.m says, socket.available returns 0 whereas it should not!!!

Is there’s a bug or something that I do not understand in tcp transfert?

Yep I was editing my message while you were writing your last post.

What is your feeling about this? is it a bug?

Voted !