c#Async Socket.BeginSendFile只发送两个异步文件

时间:2013-01-30 16:10:44

标签: c# .net sockets asyncsocket

我很困惑为什么我的 Socket.BeginSendFile 一次只发送两个异步文件。我在不同的计算机上测试过相同的结果。

Socket.BeginSend 似乎会按预期一次发送所有三个。

我测试了将三个客户端连接到服务器。哪个效果很好,三个都按预期连接异步。每个客户端(图片中的Test100.exe,Test200.exe,Test300.exe)将从服务器请求名为100,200或300的文件夹中的文件,具体取决于连接的客户端。

问题是 Socket.BeginSendFile 一次只能将最多两个文件发送到流上。只要之前称为 Socket.BeginSendFile 的2个中的一个已经完成。见下文; enter image description here

前两个客户端中的一个发送完成发送后,第三个客户端开始接收。

enter image description here

在代码中加入一些断点,我可以告诉所有三个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);


    }

第三个Socket.BeginSendFile(...)实际上并没有开始发送文件,直到前两个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 ,因为它会在单独的线程上对文件进行分块,特别是这行代码byte[] fileData = File.ReadAllBytes(longFileName);与我的 Socket.BeginSend 结构对于大文件是不可接受的:(

非常感谢您的时间!

1 个答案:

答案 0 :(得分:2)

BeginSendFile很可能使用Windows API函数TransmitFile来完成它的工作。此API仅限于在客户端版本的Windows上进行2次并发传输。

  

Windows的工作站和客户端版本通过将系统上允许的并发TransmitFile操作数限制为最多两个来优化TransmitFile功能,以实现最小的内存和资源利用率。在Windows Vista,Windows XP,Windows 2000 Professional和Windows NT Workstation 3.51及更高版本中,只有两个未完成的TransmitFile请求同时处理;第三个请求将等到之前的一个请求完成。