【问题标题】:C# bytes only sent at the end of code... [Sockets]C# 字节仅在代码末尾发送... [套接字]
【发布时间】:2017-10-28 18:30:52
【问题描述】:

我是 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 ?!
        }
    }
}

这里只有在关闭程序时才会发送套接字(因为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

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

【问题讨论】:

    标签: c# sockets send exit


    【解决方案1】:

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

    为什么会这样?

    由于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
    

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

    更好的解决方案 - 通过释放资源来强制执行

    如果您处置/关闭您的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 字节的标头和正在发送的数据组成。当使用 TCP 发送小数据包时,TCP 标头产生的开销可能成为网络流量的重要组成部分。在负载较重的网络上,这种开销导致的拥塞可能导致数据报丢失和重传,以及过多由拥塞引起的传播时间。如果连接上的任何先前传输的数据仍未得到确认,则当新的传出数据从用户到达时,Nagle 算法会禁止发送新的 TCP 段。

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

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

    【讨论】:

    • 哦,非常感谢,现在可以正常使用了,我只是有另一个问题。
    • 现在如何在 while 内使用 networkStream 接收和发送新行?我无法创建它的另一个实例...
    • 是的,我必须等待 90 分钟才能发布一个新问题,所以我会在它完成后链接它。非常感谢你帮助我:D
    • @NoBravesStudio - 你应该阅读这篇文章让你快速上手 msdn.microsoft.com/en-us/library/w89fhyex(v=vs.110).aspx
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-02
    • 2010-11-13
    • 1970-01-01
    • 2011-07-11
    • 1970-01-01
    • 2018-10-25
    • 1970-01-01
    相关资源
    最近更新 更多