我很困惑为什么我的 Socket.BeginSendFile 一次只发送两个异步文件。我在不同的计算机上测试过相同的结果。
Socket.BeginSend 似乎会按预期一次发送所有三个。
我测试了将三个客户端连接到服务器。哪个效果很好,三个都按预期连接异步。每个客户端(图片中的Test100.exe,Test200.exe,Test300.exe)将从服务器请求名为100,200或300的文件夹中的文件,具体取决于连接的客户端。
问题是 Socket.BeginSendFile 一次只能将最多两个文件发送到流上。只要之前称为 Socket.BeginSendFile 的2个中的一个已经完成。见下文;
前两个客户端中的一个发送完成发送后,第三个客户端开始接收。
在代码中加入一些断点,我可以告诉所有三个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 结构对于大文件是不可接受的:(
非常感谢您的时间!
答案 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请求同时处理;第三个请求将等到之前的一个请求完成。