开发者

TcpClient BottleNeck

I'm trying to create a self-contained class which maintains a Tcp connection to a server.

I'm using the following class variables:

TcpClient tcpClient;
NetworkStream networkStream;
BinaryReader mReader;
BinaryWriter mWriter;

And initializing them using the following code:

tcpClient = new TcpClient(host, 开发者_开发问答443);
networkStream = tcpClient.GetStream();
mReader = new BinaryReader(networkStream);
mWriter = new BinaryWriter(networkStream);

receiveMessage = new Thread(new ThreadStart(ReceiveMessages));
receiveMessage.Start();

I'm using blocking calls for the reading. Each packet coming from the server is prefixed with 4 bytes (an int) which define the exact packet size. I'm using a class I wrote named ByteBuffer which has a List(Byte) to store the bytes once they come in. The class has functions which pull ints and other types off of the top of the byte list using ReadInt(), ReadString() etc, according to the server protocol.

Here is the Receiver thread:

private void ReceiveMessages()
{
    while (tcpClient.Connected)
    {
        if (tcpClient.Available >= 4)
        {
            try
            {
                ByteBuffer message = new ByteBuffer();
                message.AddBytes(mReader.ReadBytes(4));
                int mSize = message.ReadInt();
                message.AddBytes(mReader.ReadBytes(mSize - 4));
                MessageProcessor.Process(message);
            }
            catch (Exception ex)
            {
               Print(ex.Message);
            }
        }
        Thread.Sleep(1);
    }
    Print("Receiver thread terminated.");
    Reconnect();
}

For reference, the MessageProcessor is a static class which looks at the packet information and responds to the server appropriately.

My problem is that when the traffic on the connection begins to get really high, the responses begin to get significantly delayed. I'm wondering, is there something I'm doing incorrectly as far as the tcp connection is concerned? Should I try writing an asynchronous version of the class instead? Is the C# List object too slow to be used this frequently (in the ByteBuffer)?

This is really my first attempt at network programming, so any advice would be extremely helpful.

Thanks.


I would rewrite your ReceiveMessages method like so Removes the Thread.Sleep which is bad. Uses byte arrays which are faster.

Like @jgauffin said Async network code is much better but it is easier to mess up. If you are just starting with network programming better keep it simple.

I hope this works better for you.

Note message is without the 4 byte header

private void ReceiveMessages()
    {

        while (tcpClient.Connected) {
            try {

                var networkstream = tcpClient.GetStream();
                var header = new byte[4];
                networkstream.Read(header, 0, 4);

                int len = 0;
                // calculate length from header
                // Do reverse for BigEndian, for little endian remove
                Array.Reverse(header);
                len = BitConverter.ToInt32(header, 0);

                var message = new byte[len];
                networkstream.Read(message, 0, message.Length);

                // Process message

            }
            catch (Exception ex)
            {
                Print(ex.Message);
                // Exit loop something went wrong
                break;
            }
        }

        Print("Receiver thread terminated.");
        Reconnect();

    }


Switch to asynchronous handling instead. Using a thread and Thread.Sleep is evil.

Look at Socket.BeginReceive or in your case NetworkStream.BeginRead

You could also use my new library: http://blog.gauffin.org/2012/05/griffin-networking-a-somewhat-performant-networking-library-for-net/

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜