C# TcpClient Socket.Send() 接受非常大量的数据,没有剩余字节
C# TcpClient Socket.Send() accepting very large amounts of data, no left over bytes
我正在使用 C# TcpClient 按以下方式发送几个数据包,它工作正常,但是 Send() 一次性接受 2MByte 的数据,所以我的上传进度计数器工作不正常..
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)
{
}
}
}
我的调试输出如下,我已经验证了这个 2mb 的数据包最终到达了另一端,尽管我的本地 Tcp 客户端声称它是用完整负载的 return 值立即发送的..
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%
所以我的问题是如何真实地获得上传实际进度的反馈,因为我知道它在后台花费时间,或者我如何制作 C# Socket.Send()
表现得更像 Linux send()?
您需要将发送的内容切成更小的部分。您的代码
int sendret = client.sock.Send(transmit_data, Transmit_offset, transmit_data.Length - Transmit_offset, SocketFlags.None);
会很乐意一次发送一大块,这正是你不想要的。按照
的方式尝试一些东西
int sendsize = transmit_data.Length - Transmit_offset;
if (sendsize > 8860) sendsize = 8860;
int sendret = client.sock.Send(transmit_data, Transmit_offset, sendsize, SocketFlags.None);
当然,硬编码 8860(这是 MTU 9000 的最大有效负载)不是一个好主意,请使用常量!
编辑
要了解性能影响,有必要了解
- 当数据放入最终发送缓冲区时,对
Send()
的调用将return,而不是物理上已发送并确认
- 与物理发送数据所花费的时间相比,调用开销很小(慢速机器上的 10GE 可能有不同的规则)
这意味着,下一个 Send()
可能根本不会延迟:它将在前一个数据包在线上之前准备好下一个数据包,从而使线路保持全速。
这也意味着,您的进度计数器仍然略微关闭:它将显示准备发送的数据包的进度,而不是正在发送和确认的数据包的进度。在任何宽带连接上,人类都不太可能注意到这一点。
我正在使用 C# TcpClient 按以下方式发送几个数据包,它工作正常,但是 Send() 一次性接受 2MByte 的数据,所以我的上传进度计数器工作不正常..
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)
{
}
}
}
我的调试输出如下,我已经验证了这个 2mb 的数据包最终到达了另一端,尽管我的本地 Tcp 客户端声称它是用完整负载的 return 值立即发送的..
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%
所以我的问题是如何真实地获得上传实际进度的反馈,因为我知道它在后台花费时间,或者我如何制作 C# Socket.Send() 表现得更像 Linux send()?
您需要将发送的内容切成更小的部分。您的代码
int sendret = client.sock.Send(transmit_data, Transmit_offset, transmit_data.Length - Transmit_offset, SocketFlags.None);
会很乐意一次发送一大块,这正是你不想要的。按照
的方式尝试一些东西int sendsize = transmit_data.Length - Transmit_offset;
if (sendsize > 8860) sendsize = 8860;
int sendret = client.sock.Send(transmit_data, Transmit_offset, sendsize, SocketFlags.None);
当然,硬编码 8860(这是 MTU 9000 的最大有效负载)不是一个好主意,请使用常量!
编辑
要了解性能影响,有必要了解
- 当数据放入最终发送缓冲区时,对
Send()
的调用将return,而不是物理上已发送并确认 - 与物理发送数据所花费的时间相比,调用开销很小(慢速机器上的 10GE 可能有不同的规则)
这意味着,下一个 Send()
可能根本不会延迟:它将在前一个数据包在线上之前准备好下一个数据包,从而使线路保持全速。
这也意味着,您的进度计数器仍然略微关闭:它将显示准备发送的数据包的进度,而不是正在发送和确认的数据包的进度。在任何宽带连接上,人类都不太可能注意到这一点。