I am using C# TcpClient in the following way to send a few packets,it is working correctly, but Send() is accepting 2MByte of data in one shot, so my upload progress counter is not working correctly..
Console.WriteLine("New transmit pack len={0}", transmit_data.Length);
while ((Transmit_offset < transmit_data.Length) && (client.sock.Poll(0, SelectMode.SelectWrite)))
{
int sendret = client.sock.Send(transmit_data, Transmit_offset, transmit_data.Length - Transmit_offset, SocketFlags.None);
//#if SocketDebug
Console.WriteLine("Sent " + sendret + " bytes");
//#endif
Transmit_offset += sendret;
BytesOut += sendret;
if (transmit_data.Length > 512)
{
double progress = ((double)Transmit_offset / (double)transmit_data.Length) * 100;
Console.WriteLine("Upload offset=" + offset + " packetlen="+PacketLen + " progress="+progress);
//Console.WriteLine("Data transfer complete!");
UploadProgress = Convert.ToInt32(progress);
// Console.WriteLine("Up={0}", UploadProgress);
if (progress > 100)
{
}
}
}
My Debug output is the following, and i have verified that this 2mb packet eventually arrives at the other end, despite my local Tcp Client claiming that it was sent immediately with the return value of the full payload..
SendBufferSize=8192
New transmit pack len=47
Sent 47 bytes
Connected
Sending file Server v1.56.exe....
New transmit pack len=79
Sent 79 bytes
New transmit pack len=2222367
Sent 2222367 bytes
Upload offset=0 packetlen=11504 progress=100
Upload Progress: 100%
Upload Progress: 100%
Upload Progress: 100%
Upload Progress: 100%
So my question is how to realistically get feedback of the real progress of the upload because i know its taking its time in the background, or how do i make C# Socket.Send() behave more like Linux send()?
You need to cut the send into smaller pieces. Your code
int sendret = client.sock.Send(transmit_data, Transmit_offset, transmit_data.Length - Transmit_offset, SocketFlags.None);
will happily send a big chunk at once, which is exactly what you don't want. Try something along the lines of
int sendsize = transmit_data.Length - Transmit_offset;
if (sendsize > 8860) sendsize = 8860;
int sendret = client.sock.Send(transmit_data, Transmit_offset, sendsize, SocketFlags.None);
Ofcourse hardcoding 8860 (which is max payload for MTU 9000) is a bad idea, use a constant!
EDIT
To understand the performance implications it is necessary to understand, that
Send()
will return, when data is put in the final send buffer, not when it is physically sent and acknowledgedThis means, that the next Send()
is likely not to delay things at all: It will have prepared the next packet, before the previous one is on the wire, thus keeping the line at full speed.
This also implies, that your progress counter is still slightly off: It will show the progress of the packets being ready to send, not those being sent and acknowledged. On any broadband connection this is very unlikely to be noticable to a human being.