通过套接字缓慢下载

时间:2013-03-11 07:57:44

标签: c# sockets networking tcp client-server

我在C#中用TCP编写了一个专有协议(客户端和服务器),它将文件从客户端发送到服务器,反之亦然。

由于它在概念上是全双工的,因此客户端和服务器的接收和发送方法都是相同的。

该协议允许client1将文件上传到server,一旦文件被缓冲(在服务器上),client1可以决定client2和/或client3获取文件。 (server可以仅将client2发送给client3,也可以同时发送给client1,具体取决于client2的请求。

问题是我目睹了服务器的数据传输速度慢 - >客户端,当客户端的实际带宽要高得多时,大约140 kb / s,显然也适用于服务器。

起初我认为这只是这个特定连接的最大带宽(我家和远程服务器的客户端),但是当我打开时,我看到传输速率加倍在我的电脑上{1}}和client3让服务器同时向他们发送文件;每个客户端都保持不变,但由于它们都在同一台PC上,因此本地网络的总吞吐​​量翻了一番。

  1. 关于我的问题在哪里的任何想法?如何增加服务器 - >客户转移率达到最大值?
  2. 我的代码的任何一般改进点都将受到高度赞赏。
  3. 这是我的代码:

    struct ReceiveBuffer
    {
        public const int BUFFER_SIZE = 1024 * 16;
        public byte[] BUFFER;
        public int ToReceive;
        public MemoryStream BufStream;
    
        public ReceiveBuffer(int toRec)
        {
            BUFFER = new byte[BUFFER_SIZE];
            ToReceive = toRec;
            BufStream = new MemoryStream(toRec);
        }
    }
    
    struct SendBuffer
    {
        public const int BUFFER_SIZE = 1024 * 16;
        public byte[] BUFFER;
        public int sent;
    
        public SendBuffer(byte[] data)
        {
            BUFFER = new byte[data.Length];
            Buffer.BlockCopy(data, 0, BUFFER, 0, data.Length);
            sent = 0;
        }
    }
    
    public void ReceiveAsync()
    {
        try
        {
            socket.BeginReceive(lenBuffer, 0, 4, SocketFlags.None,
                                receiveCallback, null);                
        }
        catch (SocketException se)
        {
             //handle disconnection
        }
    
    }
    
    void receiveCallback(IAsyncResult ar)
    {
        try
        {
            int rec = socket.EndReceive(ar);
            if (rec == 0)
            {
                if (Disconnected != null)
                {
                    Disconnected(this);
                    return;
                }
            }
    
            if (rec != 4)
            {
                //less than 4 bytes received...error
                return;
            }
    
            receiveBuffer = new ReceiveBuffer(BitConverter.ToInt32(lenBuffer, 0));
            socket.BeginReceive(receiveBuffer.BUFFER, 0,
                                receiveBuffer.BUFFER.Length,
                                SocketFlags.None, receivePacketCallback, null);
        }
        catch (SocketException se)
        {
            //raise disconnection event
        }
    }
    
    void receivePacketCallback(IAsyncResult ar)
    {
        try
        {
            int rec = socket.EndReceive(ar);
            if (rec <= 0)
            {
                return;
            }
            receiveBuffer.BufStream.Write(receiveBuffer.BUFFER, 0, rec);
            receiveBuffer.ToReceive -= rec;
            if (receiveBuffer.ToReceive > 0)
            {
                Array.Clear(receiveBuffer.BUFFER, 0, receiveBuffer.BUFFER.Length);
                socket.BeginReceive(receiveBuffer.BUFFER, 0,
                                    receiveBuffer.BUFFER.Length,
                                    SocketFlags.None, receivePacketCallback, null);
                return;
            }
    
            if (DataReceived != null)
            {
                //raise dataReceived event
            }
            receiveBuffer.Dispose();
            if (socket !=null)
                ReceiveAsync();
    
        }
        catch (SocketException se)
        {
            //handle disconnection
        }
    
    }
    
    // Send Async
    public void SendAsyncString(string str, CommandsToClient cmd)
    {
        BinaryWriter bw = new BinaryWriter(new MemoryStream());
        bw.Write((int)cmd);
        bw.Write((int)str.Length);
        bw.Write(Encoding.ASCII.GetBytes(str));
        bw.Close();
        byte[] data = ((MemoryStream)(bw.BaseStream)).ToArray();
        bw.BaseStream.Dispose();
        SendAsync(data);
    }
    
    public void SendAsync(byte[] data)
    {
        int toSend;
        byte[] dataWithHeader = Combine(BitConverter.GetBytes(data.Length), data);
        sendBuffer = new SendBuffer(dataWithHeader);
        if (sendBuffer.BUFFER.Length - sendBuffer.sent > SendBuffer.BUFFER_SIZE)
            toSend = SendBuffer.BUFFER_SIZE;
        else
            toSend = sendBuffer.BUFFER.Length - sendBuffer.sent;
        socket.BeginSend(sendBuffer.BUFFER, 0,toSend, SocketFlags.None,
                         sendCallback, null);
    }
    
    void sendCallback(IAsyncResult ar)
    {
        try
        {
            int bytesSent = socket.EndSend(ar);
            if (bytesSent == 0)
            {
                //raise disconnection event
            }
            sendBuffer.sent += bytesSent;
            if (sendBuffer.sent==sendBuffer.BUFFER.Length)
            {
                sendBuffer.Dispose();
                return;
            }
            int toSend;
            if (sendBuffer.BUFFER.Length - sendBuffer.sent > SendBuffer.BUFFER_SIZE)
                toSend = SendBuffer.BUFFER_SIZE;
            else
                toSend = sendBuffer.BUFFER.Length - sendBuffer.sent; 
    
            socket.BeginSend(sendBuffer.BUFFER, sendBuffer.sent,toSend,
                            SocketFlags.None, sendCallback, null);
        }
        catch (SocketException se)
        {
            //hande disconnection
        }
    }
    

1 个答案:

答案 0 :(得分:0)

似乎放缓我速度的是缓冲区大小。

在我的电脑上: 我可以上传@约50 KBytes / sec
我可以下载@约600 KBytes / sec (这些值显然会发生变化,具体取决于远程主机,但它确实给出了很好的估计值)

在服务器上: 上传和下载更高的带宽(几十兆字节)

这是我现在使用的设置,它允许我高传输率:

在客户端(我的电脑)

Receive Buffer = 128 Kbytes
Send    Buffer = 32  Kbytes

在服务器端:

Receive Buffer =  64 Kbytes
Send    Buffer =  256 Kbytes