tags:

views:

73

answers:

2

First i am n00b in socket programming. So i decided to write simple data over lan tcp server My server code that handles incomming data is

    private void HandleClientComm(object client)
{

    TcpClient tcpClient = (TcpClient)client;
    NetworkStream clientStream = tcpClient.GetStream();
    clientStream.ReadTimeout = 10;
    int size = 4096 * 1000;
    byte[] message = new byte[size];
    byte[] All = new byte[0];
    int bytesRead;
    string error = "";
    lock (this)
    {
        while (true)
        {
            All = new byte[0];
            while (true)
            {
                bytesRead = 0;
                try
                {
                    bytesRead = clientStream.Read(message, 0, size);
                    All = AddBArrays(All, message, bytesRead);
                }
                catch
                {
                    break;
                }

                if (bytesRead == 0)
                {
                    break;
                }

            }
            if (All.Length > 0)
            {
                Message m = (Message)Tools.ByteArrayToObject(All);
                OnRecived(new RecivedArgs("localhost", (Message)Tools.ByteArrayToObject(All)));
            }
        }
        tcpClient.Close();
    }
}
byte[] AddBArrays(byte[] ar1, byte[] ar2, int read)
{
    byte[] concat = new byte[ar1.Length + read];
    if (ar1.Length != 0)
        System.Buffer.BlockCopy(ar1, 0, concat, 0, ar1.Length);
    System.Buffer.BlockCopy(ar2, 0, concat, ar1.Length, read);
    return concat;
}

it works but have some issues. It fales receiving files bigger then 100 mbs or smthng and also if i send data very often interval < 800 then data is lost. how should i improve my code? The large file issue is not so important the primary issue is the data loss in fast data sending. tnx for help

Ok i now updated the code by the suggestions

private void HandleClientComm(object client)
{

    TcpClient tcpClient = (TcpClient)client;
    NetworkStream clientStream = tcpClient.GetStream();
    clientStream.ReadTimeout = 10;
    int size = 4096 * 1000;
    List<byte> Test = new List<byte>();
    byte[] message = new byte[size];
    byte[] All = new byte[0];
    int bytesRead;
    while (true)
    {
        //All = new byte[0];
        while (true)
        {
            bytesRead = 0;
            try
            {
                bytesRead = clientStream.Read(message, 0, size);
                for (int i = 0; i < bytesRead; i++)
                {
                    Test.Add(message[i]);
                }
            }
            catch
            {
                break;
            }

            if (bytesRead == 0)
            {
                break;
            }
        }
        if (Test.Count > 0)
        {
            Message m = (Message)Tools.ByteArrayToObject(Test.ToArray());
            OnRecived(new RecivedArgs("localhost", m));
            Test = new List<byte>();
        }
    }
    tcpClient.Close();

}

but the issues still there

Edit--> large file issue fixed it was just a 'System.OutOfMemoryException' but it didn't throw a error.

A: 
  • The All byte array you should change to a List<byte>. You are creating instances like crazy right now. The GC is probably working a lot more than it needs to. This might be slowing it down so much that it can't keep up.

Not really related to sockets:

  • Make size a const
  • NEVER lock this. Create a private field that you can lock. In fact, I don't even think you need a lock here.
  • remove the error string.
Bryan
* Use AddRange() for adding to the List<byte>
Bryan
done that but still same issues
Woland
also addrange copy's all message to List but most of times it is filled only by 250 bytes of data other is just zeros and i consider it a big waste of memory.
Woland
A: 

OK i solved the problem. I simple send to much data to fast so data loss was unavoidable.

My optimized code is

private void HandleClientComm(object client)
{
    TcpClient tcpClient = (TcpClient)client;
    NetworkStream clientStream = tcpClient.GetStream();
    int size = 1;
    byte[] message = new byte[1];
    int bytesRead;
    while (true)
    {
        bytesRead = 0;
        if (clientStream.DataAvailable)
            bytesRead = clientStream.Read(message, 0, 1);
        if (bytesRead > 0)
        {
            OnRecived(new RecivedArgs("tick", null));
        }
        Thread.Sleep(1);
    }
}

i have tested intervals as low as 1 ms and no data loss :) thanks for your help

Woland