C# 字节仅在代码末尾发送... [套接字]

C# bytes only sent at the end of code... [Sockets]

我是 C# 的新手,这是我的第一个代码:D 过去我在 Java 中编码,现在我在发送套接字时遇到了很多麻烦。 当我尝试发送一个套接字时,它只在代码的最后发送: 例如

    using System;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.IO;
using System.Text;

namespace HelloWorld
{
    class Program
    {
        public static TcpClient client;
        public static NetworkStream networkStream;

        public static void Main(string[] args)
        {
            client = new TcpClient("62.210.130.212", 35025);
            networkStream = client.GetStream();
            byte[] usernameBytes = Encoding.ASCII.GetBytes("This is just a test bro!");
            networkStream.Write(usernameBytes, 0, usernameBytes.Length);
            networkStream.Flush();

            while (true)
            {
                // Infinte loop
            }
            // THE SOCKER WILL ONLY BE SENT HERE, AT THE END OF THE CODE, WHY ?!
        }
    }
}

这里socket只会在程序关闭时发送(因为wile循环)

这里

using System;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.IO;
using System.Text;

namespace HelloWorld
{
    class Program
    {
        public static TcpClient client;
        public static NetworkStream networkStream;

        public static void Main(string[] args)
        {
            client = new TcpClient("62.210.130.212", 35025);
            networkStream = client.GetStream();
            byte[] usernameBytes = Encoding.ASCII.GetBytes("This is just a test bro!");
            networkStream.Write(usernameBytes, 0, usernameBytes.Length);
            networkStream.Flush();
        }
    }
}

并且在这种情况下会直接发送,因为它是代码的结尾...

有谁知道为什么会发生这种情况以及如何解决?我希望在 运行 时间的任何时间发送我的套接字,而不仅仅是在结束时:D

非常感谢!感谢您阅读这个问题直到那里。 朱利安

Does anyone know why this happens and how to fix it? I want my sockets to be sent at any time of the running time, not just at the end.

为什么会这样?

由于Nagle's algorithm,传输将短暂延迟(以毫秒为单位)。

这意味着您的代码在进入循环之前没有提供足够的时间。

networkStream.Write(usernameBytes, 0, usernameBytes.Length);
networkStream.Flush();

// the time between here is not enough for nagle's algorithm to complete

while (true) { } // blocks the thread from doing any more work

// so, it will end up sending here instead.

如何解决?

快速解决方案 - 禁用 Nagle 算法

this answer 中所述,您可以将 TcpClient.NoDelay 设置为 true 以禁用 Nagle 算法。

您可以通过将其添加到您的代码中轻松完成此操作:

 client = new TcpClient("62.210.130.212", 35025);
 client.NoDelay = true; // add this line of code to disable Nagle's algorithm

注意:此解决方案将强制立即发送。但是,由于您的问题不清楚具体要求,请注意这可能不是“最佳”解决方案。

更好的解决方案 - 通过处置您的资源强制执行

如果你 dispose/close 你的 TcpClient 它会完成同样的事情。此外,它将提供额外的(和更好的做法)在您使用完资源后立即处理资源。

public static void Main(string[] args)
{
    using (TcpClient client = new TcpClient("62.210.130.212", 35025))
    using (NetworkStream networkStream = client.GetStream())
    {
        byte[] usernameBytes = Encoding.ASCII.GetBytes("This is just a test bro!");
        networkStream.Write(usernameBytes, 0, usernameBytes.Length);
    }

    while (true) { } // loop infinitely
}

注意:这实际上并不像上面的解决方案那样立即发送数据包,而是强制发送数据包,因为我们正在关闭它。但是,您的情况的结果是相同的,这是您应该练习的更好的方法。


什么是 Nagle 算法?

Nagle 算法旨在通过使套接字缓冲小数据包然后在特定情况下将它们组合并发送到一个数据包中来减少网络流量。

一个 TCP 数据包由 40 个字节的 header 加上要发送的数据组成。当使用 TCP 发送小数据包时,TCP header 产生的开销可能成为网络 traffic.On 重负载网络的重要部分,这种开销导致的拥塞可能导致数据报丢失和重传,以及拥塞造成的传播时间过长。 Nagle 算法禁止在新的传出数据从用户到达时发送新的 TCP 段,如果连接上的任何先前传输的数据仍未得到确认。

大多数网络应用程序应该使用 Nagle 算法。

在用户数据报协议 (UDP) 套接字上设置此 属性 将无效。