【问题标题】:C# TcpClient Socket.Send() accepting very large amounts of data, no left over bytesC# TcpClient Socket.Send() 接受非常大量的数据,没有剩余字节
【发布时间】:2015-03-07 07:53:45
【问题描述】:

我正在使用 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 客户端声称它是立即发送的,并带有完整有效负载的返回值..

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()?

【问题讨论】:

    标签: c# sockets tcpclient


    【解决方案1】:

    您需要将发送切成小块。你的代码

    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() 的调用将在数据放入最终发送缓冲区时返回,而不是在实际发送并确认时返回
    • 与物理发送数据所需的时间相比,调用开销很小(慢速机器上的 10GE 可能有不同的规则)

    这意味着,下一个Send() 可能根本不会延迟任何事情:它将在前一个数据包上线之前准备好下一个数据包,从而保持线路全速。

    这也意味着您的进度计数器仍然略微关闭:它将显示准备发送的数据包的进度,而不是那些正在发送和确认的数据包的进度。在任何宽带连接上,人类都不太可能注意到这一点。

    【讨论】:

    • 我在想这个,但后来我也认为这是一个坏主意,因为它会显着减慢速度.....我认为有一种方法可以让 C# 发送尽可能多的内容can like Linux send()..... 我相信会发生的问题是,当我发送 8860 个块时,无论如何它们都会在很短的时间内连续发送。
    • 好吧,我已经用 localhost 试过了,上传速度非常快,然后我通过 512k ADSL 尝试了我的远程服务器,上传速度确实很慢。这很奇怪!快乐。
    猜你喜欢
    • 2019-06-30
    • 2022-01-12
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-13
    相关资源
    最近更新 更多