1

Socket.BeginSendFileが一度に2つのファイルしか非同期で送信しない理由に戸惑っています。別のコンピューターでテストしたところ、同じ結果になりました。

Socket.BeginSendは、期待どおりに3つすべてを一度に送信するようです。

3つのクライアントをサーバーに接続することをテストしました。これはうまく機能しますが、3つすべてが期待どおりに非同期に接続します。各クライアント(図のTest100.exe、Test200.exe、Test300.exe)は、接続しているクライアントに応じて、サーバーから100、200、または300という名前のフォルダーからファイルを要求します。

問題は、Socket.BeginSendFileが一度に最大2つのファイルのみをストリームに送信していることです。以前にSocket.BeginSendFileと呼ばれていた2つのうちの1つが終了するとすぐに。下記参照; ここに画像の説明を入力してください

送信する最初の2つのクライアントの1つが送信を終了するとすぐに、3番目のクライアントが受信を開始します。

ここに画像の説明を入力してください

コードにいくつかのブレークポイントを設定すると、3つすべてのSocket.BeginSendFile(...)が非同期と呼ばれていることがわかります。

    private static void Send(Socket handler, String data)
    {
        string dateFolder =  data.Replace("<EOF>", "");

        string longFileName = "C:\\"+dateFolder+"\\poopoo.txt";
        string shortFileName = "poopoo.txt";

        // ==== for beginSend
        //byte[] fileData = File.ReadAllBytes(longFileName);
        // ==== for beginSend


        byte[] fileNameByte = Encoding.ASCII.GetBytes(shortFileName);
        byte[] fileInfo = Encoding.ASCII.GetBytes("C:\\Users\\Trim\\Desktop");
        byte[] fileInfoLen = BitConverter.GetBytes(fileInfo.Length); // we know these are ints (4bytes)

        byte[] clientData = new byte[4 + fileNameByte.Length + fileInfoLen.Length + fileInfo.Length];// + fileData.Length + eofByte.Length
        // ==== for beginSend
        //byte[] clientData = new byte[4 + fileNameByte.Length + fileInfoLen.Length + fileInfo.Length + fileData.Length];
        // ==== for beginSend

        byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length); // we know these are int (4bytes);

        fileNameLen.CopyTo(clientData, 0);
        fileNameByte.CopyTo(clientData, 4); // room for error file name 4bytes?
        fileInfoLen.CopyTo(clientData, 4 + fileNameByte.Length);
        fileInfo.CopyTo(clientData, 4 + fileNameByte.Length + fileInfoLen.Length);

        // ==== for beginSend
        //fileData.CopyTo(clientData, 4 + fileNameByte.Length + fileInfoLen.Length + fileInfo.Length);
        // ==== for beginSend
        // *** Break point shows all three being called async
        handler.BeginSendFile(longFileName, clientData, null, 0, new AsyncCallback(AsynchronousFileSendCallback), handler);



       // handler.BeginSend(clientData, 0, clientData.Length, 0, new AsyncCallback(SendCallback), handler);


    }

3番目のSocket.BeginSendFile(...)は、最初の2つのAsynchronousFileSendCallbackメソッドのいずれかが実行されるまで、実際にはファイルの送信を開始しません。

    private static void AsynchronousFileSendCallback(IAsyncResult ar)
    {
        // Retrieve the socket from the state object.
        Socket client = (Socket)ar.AsyncState;

        // Complete sending the data to the remote device.
        client.EndSendFile(ar); // **Third** client doesn't actually start receiving his data until EndSendFile is called atleast once.

        Console.WriteLine("Send file to client.");
       // sendDone.Set();
        client.Shutdown(SocketShutdown.Both);
        client.Close();
    }

前に述べたように、Socket.BeginSendを使用すると、問題は解決します。Socket.BeginSendFileを使用できるようにする必要がありますが、これはファイルを別のスレッドでチャンク化するためです。特に、 Socket.BeginSendbyte[] fileData = File.ReadAllBytes(longFileName);構造で使用されるこのコード行は、大きなファイルでは受け入れられません:(

本当にありがとうございました!

4

1 に答える 1

2

BeginSendFile が Windows API 関数 TransmitFile を使用してジョブを実行する可能性は非常に高いです。また、この API は、クライアントバージョンの Windows では 2 つの同時転送に制限されています。

Windows のワークステーションおよびクライアント バージョンは、TransmitFile 機能を最適化して、システムで許可される同時 TransmitFile 操作の数を最大 2 つに制限することにより、メモリとリソースの使用率を最小限に抑えます。Windows Vista、Windows XP、Windows 2000 Professional、および Windows NT Workstation 3.51 以降では、2 つの未解決の TransmitFile 要求のみが同時に処理されます。3 番目の要求は、前の要求の 1 つが完了するまで待機します。

于 2013-01-30T21:01:09.367 に答える