I am puzzled at why my Socket.BeginSendFile only sends two files async at a time. I have tested on different computer with the same results.
Socket.BeginSend seems to send all three at once as expected.
I tested connecting three clients to the server. Which works great, all three connect async as expected. Each client (Test100.exe, Test200.exe, Test300.exe in picture) will request a file from either a folder named 100, 200 or 300 from the server depending on the which client connected.
The problem is that Socket.BeginSendFile is only sending max two files at a time onto the stream. As soon as one of the 2 previously called Socket.BeginSendFile have finished. See below;

As soon as one of the first two clients sending finishes the send, the third begins receiving.

Putting some breakpoints into the code, I can tell that all three Socket.BeginSendFile(…) are being called async.
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);
}
The third Socket.BeginSendFile(…) doesnt actually begin to send the file until one of the first two AsynchronousFileSendCallback methods
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();
}
As I said earlier, if I use Socket.BeginSend the issue goes away. Although I need to be able to use Socket.BeginSendFile because it chunks the file on a separate thread and particularly this line of code byte[] fileData = File.ReadAllBytes(longFileName); used with my Socket.BeginSend structure is unacceptable for large files 🙁
Thank you all very much for your time!
It’s very likely that BeginSendFile uses the Windows API function TransmitFile to do its job. And this API is limited to 2 concurrent transfers on client versions of Windows.