locked
Trouble with sending big file by C# socket and splitting file RRS feed

  • Question

  • I AMtrying to transfer a file with c# socket (UDP).

    I know i can just transfer about 60 kilobyte with and because of this I split my byte array and sending it in multi steps. but after sending one part of my array I get this exception:

    A message sent on a datagram socket was larger than the internal message buffer or some other network limit, or the buffer used to receive a datagram into was smaller than the datagram itself

    However my buffer is big enough.

    Here is my code:

    Receiver:

                Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                string selection = Console.ReadLine();
                if(selection == "server")
                {
                    IPEndPoint ep = new IPEndPoint(IPAddress.Any, 4455);
                    IPEndPoint rep = new IPEndPoint(IPAddress.Loopback, 4444);
                    EndPoint rend = (EndPoint)rep;
                    sock.Bind(ep);
                    byte[] recb = new byte[1024 * 100]; // 100 kb
                    byte[] send = new byte[256];
                    byte[] FinalFile = new byte[1024 * 100000]; // 100 mb 
                    int rec = sock.ReceiveFrom(recb, ref rend);
                    string tmp = Encoding.ASCII.GetString(recb, 0, rec);
                    Console.WriteLine("shard num rec {0}", tmp);
    
                    int shards = int.Parse(tmp);
                    int loffset = 0;
                    
                    for(int i = 1; i <= shards; i++)
                    {
                        Console.WriteLine("shard {0}", i.ToString());
                        /*if(i == 0)
                        {
                            rec = sock.ReceiveFrom(recb, ref rend);
                            Buffer.BlockCopy(recb, 0, FinalFile, 0, rec);
                            loffset = rec;
                            rec = 0;
                            recb = new byte[1024 * 10000];
                            Console.WriteLine("shard {0} out", i.ToString());
    
                            continue;
                        }*/
                        rec = sock.ReceiveFrom(recb, ref rend);
                        Buffer.BlockCopy(recb, 0, FinalFile, loffset, rec);
                        loffset += rec;
                        recb = new byte[1024 * 10000];
                        rec = 0;
                        Console.WriteLine("shard {0} out", i.ToString());
                    }
                    int size = (int)FinalFile.Length;
                    File.WriteAllBytes(@"C:\Users\Amirmohammad Farhang\Desktop\shard.max", FinalFile);
                    Console.WriteLine("done");
                }
    

    Sender:

                else
                {
                    IPEndPoint ep = new IPEndPoint(IPAddress.Any, 4444);
                    IPEndPoint rep = new IPEndPoint(IPAddress.Loopback, 4455);
                    EndPoint rend = (EndPoint)rep;
                    sock.Bind(ep);
                    byte[] recb = new byte[1024 * 100]; // 100 kb
                    byte[] send = new byte[256];
                    byte[] FinalFile = new byte[1024 * 100000]; // 100 mb 
                    string patch = Console.ReadLine();
                    FinalFile = File.ReadAllBytes(@patch);
                    FileInfo fi = new FileInfo(@patch);
                    int size = (int)fi.Length;
                    
                    int lsize = size % 60000;
                    int shard = size / 60000;
                    bool more = false;
                    if (lsize != 0)
                    {
                        more = true;
                        shard++;
                    }
                    sock.SendTo(Encoding.ASCII.GetBytes(shard.ToString()), rep);
                    int loffset = 0;
                    int rec;
                    for (int i = 1; i <= shard; i++)
                    {
                        Console.WriteLine("shard {0} in offset and size: {1} , {2}", i.ToString(), loffset.ToString(), (i*60000).ToString());
    
                        /*if (i == 1)
                        {
                            rec = sock.SendTo(FinalFile, 0, i * 60000, SocketFlags.None, rep);
                            loffset = i * 60000;
                            rec = 0;
                            recb = new byte[1024 * 10000];
                            Console.WriteLine("shard {0} out offset and size: {1} , {2}", i.ToString(), loffset.ToString(), (i * 60000).ToString());
                            continue;
    
                        }*/
                        if(i == shard--)
                        {
                            rec = sock.SendTo(FinalFile, loffset, i * lsize, SocketFlags.None, rep);
                            recb = new byte[1024 * 10000];
                            rec = 0;
                            Console.WriteLine("shard {0} out offset and size: {1} , {2}", i.ToString(), loffset.ToString(), (i * 60000).ToString());
                            break;
                        }
                        rec = sock.SendTo(FinalFile, loffset, i * 60000, SocketFlags.None, rep);
                        loffset = i * 60000;
                        recb = new byte[1024 * 10000];
                        rec = 0;
                        Console.WriteLine("shard {0} out offset and size: {1} , {2}", i.ToString(), loffset.ToString(), (i * 60000).ToString());
    
                    }
                    Console.WriteLine("done");
                }
    

    and output is like:

    receiver: shards :4 
    shard num rec 4
    shard 1
    shard 1 out
    shard 2
    
    sender:shard 1 in offset and size: 0 , 60000
    shard 1 out offset and size: 60000 , 60000
    shard 2 in offset and size: 60000 , 120000
    
    Unhandled Exception: System.Net.Sockets.SocketException: A message sent on a datagram socket was larger than the internal message buffer or some other network limit, or the buffer used to receive a datagram into was smaller than the datagram itself
    

    Note: I know i can use TCP but for holepunching i need to do this with udp.

    Thanks in advance.

    Friday, November 6, 2020 1:54 PM

All replies

  • Hi Compo_Team,

    Thank you for posting here.

    The theoretical limit (on Windows) for the maximum size of a UDP packet is 65507 bytes, but it's not the largest safe UDP packet size.

    With UDP the datagrams are not guaranteed to arrive at the other side, and UDP does not deliveres datagrams in the same order so it will be difficult to reassemble them at receiver.

    TCP is a better choice.

    >>I know i can use TCP but for holepunching i need to do this with udp.

    As for TCP Hole Punch, here are two related references you can refer to.

    1. How do I do TCP hole punching?
    2. TCP Hole Punch (NAT Traversal) Library or something?

    Hope them could be helpful.

    Best Regards,

    Xingyu Zhao


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, November 9, 2020 6:43 AM