Байты C # отправляются только в конце кода [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 ?!
        }
    }
}

Здесь сокет будет отправлен только при завершении работы программы (из-за цикла 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

Большое спасибо ! Спасибо, что дочитали этот вопрос до этого момента. Жюльен.


person No Braves Studio    schedule 28.05.2017    source источник


Ответы (1)


Кто-нибудь знает, почему так происходит и как исправить? Я хочу, чтобы мои сокеты отправлялись в любое время работы, а не только в конце.

Почему это происходит?

Из-за алгоритма Нэгла передача будет задержана на короткое время (в миллисекундах).

Это означает, что ваш код не предлагает достаточно времени, прежде чем он перейдет в цикл.

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.

Как это исправить?

Быстрое решение - отключить алгоритм Нэгла

Как описано в этом ответе, вы можете установить TcpClient.NoDelay на true, чтобы отключить алгоритм Нэгла.

Вы можете легко добиться этого, добавив его в свой код:

 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
}

Примечание: на самом деле это не отправляет пакет немедленно, как решение выше, а вместо этого заставляет пакет отправляться, потому что мы закрываем его. Однако в вашем случае результат будет таким же, и это гораздо лучший подход, который вам следует практиковать.


Что такое алгоритм Нэгла?

Алгоритм Нагла разработан для уменьшения сетевого трафика, заставляя сокет буферизовать небольшие пакеты, а затем объединять и отправлять их в один пакет при определенных обстоятельствах.

Пакет TCP состоит из 40 байтов заголовка и отправляемых данных. Когда небольшие пакеты данных отправляются с помощью TCP, накладные расходы, связанные с заголовком TCP, могут стать значительной частью сетевого трафика. В сильно загруженных сетях перегрузка, возникающая из-за этих накладных расходов, может привести к потере дейтаграмм и повторным передачам, а также чрезмерной время распространения, вызванное перегрузкой. Алгоритм Нагла запрещает отправку новых сегментов TCP при поступлении новых исходящих данных от пользователя, если какие-либо ранее переданные данные по соединению остаются неподтвержденными.

Большинство сетевых приложений должны использовать алгоритм Нагла.

Установка этого свойства для сокета протокола пользовательских дейтаграмм (UDP) не будет иметь никакого эффекта.

person Svek    schedule 28.05.2017
comment
О, спасибо большое, теперь все работает нормально, просто у меня другая проблема. - person No Braves Studio; 28.05.2017
comment
Как теперь получать и отправлять новые строки с помощью networkStream внутри while? Я не могу создать другой экземпляр ... - person No Braves Studio; 28.05.2017
comment
Да, мне нужно подождать 90 минут до публикации нового вопроса, поэтому я свяжу его, когда он будет готов. Большое спасибо за помощь мне: D - person No Braves Studio; 28.05.2017
comment
@NoBravesStudio - вы должны прочитать это, чтобы быстро приступить к работе msdn.microsoft.com/en-us/library/w89fhyex (v = vs.110) .aspx - person Svek; 28.05.2017
comment
Вот ссылка: stackoverflow.com/questions/44226506/ - person No Braves Studio; 28.05.2017