0

私は、C# で TCP の上に独自のプロトコル (クライアントとサーバー) を作成しました。これは、クライアントからサーバーへ、またはその逆にファイルを送信します。

概念的には全二重であるため、受信と送信の方法はクライアントとサーバーの両方で同じです。

このプロトコルではclient1、ファイルを にアップロードできますserver。ファイルが (サーバー上で) バッファリングされると、ファイルを取得client1するかどうかclient2を決定したりclient3取得したりできます。( は、 による要求に応じて、 のみ、 のみ、または両方に同時にserver送信できます)。client2client3client1

問題は、実際の帯域幅がクライアントとサーバーの両方ではるかに高い場合に、サーバー -> クライアントのデータ転送が遅く、約 140 kb/s になることです。

最初は、この特定の接続 (自宅のクライアントと遠隔地のサーバー) の単純な最大帯域幅だと思っていましたが、PCを開いてサーバーに両方を送信させると、転送速度が 2 倍になることがわかりました。ファイルを同時に; クライアントごとに同じままですが、両方とも同じ PC 上にあるため、ローカル ネットワークの合計スループットは 2 倍になりました。client2client3

  1. 私の問題がどこにあるのかについて何か考えはありますか? サーバー -> クライアントの転送速度を最大にするにはどうすればよいですか?
  2. 私のコードに関する一般的な改善点は高く評価されます。

これが私のコードです:

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
    }
}
4

1 に答える 1

0

私を遅くしていたのはバッファサイズだったようです。

私の PC では、アップロードできます @ 約 50 KBytes/sec
ダウンロードできます @ 約 600 KBytes/sec (これらの値は、リモート ホストによって明らかに変化しますが、適切な見積もりが得られます)

サーバー上: はるかに高い帯域幅 (数十メガバイト) のアップロードとダウンロード

これが私が現在使用している設定で、高い転送速度を可能にします:

クライアント側(私のPC)

Receive Buffer = 128 Kbytes
Send    Buffer = 32  Kbytes

サーバー側:

Receive Buffer =  64 Kbytes
Send    Buffer =  256 Kbytes
于 2013-03-11T16:59:30.277 に答える