Как отправить «n» пакетов с помощью TcpClient, используя c#/.Net

#c# #.net #sockets #server #tcpclient

Вопрос:

Я пытаюсь отправить несколько пакетов с помощью TcpClient. этот код работает на первой итерации. но после первой итерации сервер ничего не получает(хотя цикл продолжает повторяться). код на стороне сервера работает нормально, так как я тестировал его с отправителем пакетов. Что-нибудь для отправки пакетов с помощью TcpClient?

 TcpClient tcpClient = new TcpClient(localIpAddress,localPort);
            tcpClient.NoDelay = true;
            tcpClient.Connect(remoteIpAddress,remotePort);
            Stream stream=tcpClient.GetStream();
            int i = 0;
            while (true)
            {
                i = i   1;
                Console.WriteLine("Message {0} Sent",i);
                stream.Write(Encoding.ASCII.GetBytes(message))));
                stream.Flush();
                Thread.Sleep(500);
                
            } 
 

Комментарии:

1. пакеты-это то, как реализуется протокол TCP, но как пользователь вы должны быть совершенно не осведомлены о них. Абстракция, которую предоставляет TCP, представляет собой бесконечный поток байтов . Если вы хотите разбить этот поток на пакеты или сообщения, вам нужно реализовать такое обрамление поверх бесконечного потока байтов (или перейти к протоколу более высокого уровня, который делает это за вас).

Ответ №1:

Вы не можете точно контролировать отправку пакетов с помощью TcpClient. На самом деле вы даже не можете сделать это с помощью TCP-сокета(). Вам нужно будет использовать необработанный сокет и структурировать свои собственные TCP-пакеты.

Стек TCP решает, когда он собирается отправить пакет, на основе параметров конфигурации сокета, количества информации в буфере, времени последнего подтверждения, размера окна, RTT и некоторых других вещей.

Вы можете обмануть его, отправив много данных, что заставит стек TCP отправлять их немедленно так быстро, как только сможет. Вы также можете установить TcpClient.NoDelay() , но это не будет работать для нескольких последовательных записей, если у вас нет разумной задержки между записями, и даже в этом случае она не гарантируется.

Вы можете совершать низкоуровневые вызовы, чтобы определить, сколько пакетов было отправлено/recv, но вы можете повлиять на это только путем настройки параметров стека TCP, и даже в этом случае он никогда не будет детерминированным из-за того, что IP-адрес является протоколом с потерями, а пакеты TCP будут отсутствовать и их необходимо будет повторно передать.

Ваша проблема с приведенным выше кодом заключается в том, что вы устанавливаете локальную точку с помощью этой строки:

 TcpClient tcpClient = new TcpClient(localIpAddress,localPort);
 

Порт не будет повторно использоваться до тех пор, пока сокет не пройдет TIME_WAIT фазу, которая, в зависимости от того, как выключение сокета может занять 120 секунд.

Измените эту строку на:

 TcpClient tcpClient = new TcpClient(); 
 

Или если вам необходимо установить исходный IP-адрес

 TcpClient tcpClient = new TcpClient(localIpAddress,0);
 

Вы можете прочитать об этом TIME_WAIT здесь и о том, почему это неотъемлемая часть протокола TCP.

В качестве примечания, stream.Flush(); или NetworkStream.Flush() абсолютно ничего не делает. Это и есть его реализация в .Чистый источник:

     /// <devdoc>
    ///    <para>
    ///       Flushes data from the stream.  This is meaningless for us, so it does nothing.
    ///    </para>
    /// </devdoc>
    public override void Flush() {
    }
 

Комментарии:

1. На самом деле я пытаюсь разработать отправителя пакетов, который использует только один порт для отправки пакетов. так что любая помощь в плане изменений кода будет признательна!!

2. Если вы хотите установить исходный порт и хотите каждый раз запускать новое соединение, вам нужно будет дождаться истечения времени ожидания старого соединения из стека TCP, прежде чем вы сможете использовать его повторно. Это по замыслу и является частью протокола TCP.

3. зачем мне ждать завершения старого соединения, когда мне просто нужно отправить несколько пакетов по одному и тому же соединению?

4. Ссылка, которую я включил выше, объясняет процесс демонтажа, задержка является частью стека TCP. Этого нельзя избежать, если вы хотите повторно использовать исходный порт до истечения времени ожидания, которое может составлять от 0 до 120 секунд, в зависимости от того, как произошло отключение сокета в сети.