Как сгенерировать флаг [FIN], когда я отправил строку, используя соединение TCPIP с [FIN, PSH, ACK]

#.net #tcp

#.net #tcp

Вопрос:

Я пытаюсь эмулировать клиентскую программу, которая взаимодействует с существующим сервером. Я использовал wireshark и могу видеть сообщения туда и обратно. Клиентская программа подключается и отправляет строку

 9 0 0 99 3 0 CR LF 
CLIENT SEND
0.001157    192.168.0.210   192.168.0.197   TCP 69  6151722223 [PSH, ACK] Seq=1 Ack=1 Win=131328 Len=15
  

затем пустая строка просто

 CR LF
0.001232    192.168.0.210   192.168.0.197   TCP 56  61517 → 22223 [FIN, PSH, ACK] Seq=16 Ack=1 Win=131328 Len=2
  

сервер отвечает подтверждением подтверждения и возвращаемым текстовым сообщением, за которым следует CR LF

 SERVER RESPONSE
0.002383    192.168.0.197   192.168.0.210   TCP 60  22223 → 61517 [ACK] Seq=1 Ack=19 Win=525568 Len=0
0.004112    192.168.0.197   192.168.0.210   TCP 66  22223 → 61517 [PSH, ACK] Seq=1 Ack=19 Win=525568 Len=12
0.004113    192.168.0.197   192.168.0.210   TCP 60  22223 → 61517 [FIN, PSH, ACK] Seq=13 Ack=19 Win=525568 Len=2
  

Когда я пытаюсь эмулировать клиента — все кажется одинаковым, ЗА ИСКЛЮЧЕНИЕМ ТОГО, что я не получаю [FIN, PSH, ACK], а только [PSH, ACK], и сервер не отвечает.
В своих экспериментах я обнаружил, что если я закрываю поток после записи на сервер, я вижу на wireshark, что ответ отправлен (но теперь ссылка закрыта, поэтому я не могу ее получить)
Кто-нибудь знает, как сгенерировать [FIN, PSH, ACK], оставив соединение активным??

МОЯ ПРОЦЕДУРА ОТПРАВКИ СООБЩЕНИЙ

 Public Async Sub SendMessage(ByVal msg As String) 'Handles sendButton.Click
    Try

        If client IsNot Nothing AndAlso client.Connected Then

            Dim stream As NetworkStream = client.GetStream
            Dim myBytes2() As Byte = Encoding.Default.GetBytes(msg)
            Try
                Await stream.WriteAsync(myBytes2, 0, myBytes2.Length)
                'stream.Close()
            Catch ioex As System.IO.IOException
                DisplayLog("Server terminated connection")
            Catch odex As ObjectDisposedException
                DisplayLog("client terminated connection")
            Catch er As Exception
                DisplayLog("ERROR Module:{" amp; GetModuleName(er) amp; "}" amp; Information.Err().Number amp; " Mess:" amp; er.Message)
            End Try
        End If
    Catch er As Exception
        DisplayLog("ERROR Module:{" amp; GetModuleName(er) amp; "}" amp; Information.Err().Number amp; " Mess:" amp; er.Message)
    End Try


End Sub
  

Ответ №1:

Я думаю, у вас неправильные ожидания относительно того, как работает TCP. FIN — это не конец какого-либо сообщения, а конец полного соединения. Поэтому она отправляется при закрытии потока, но не после сообщения.

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

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

1. Спасибо за ваш ответ, Штеффен, да, действительно, я не совсем понимаю TCP. Однако я написал много клиентов для TCP-серверов и не сталкивался с этим конкретным сценарием. При мониторинге соединения с помощью Wireshark единственное, что я вижу, отличается от моего клиента от существующего клиента, так это то, что после отправки строки на сервер с помощью [PSH, ACK] [FIN, PSH, ACK] отправляется с завершающей строкой CR, LF . Без этого FIN (или закрытого соединения) сервер не отправит ответ… Запутался… Пол

2. @Paul: То, что вы описываете, необычно в общении, но не невозможно: клиент выполняет одностороннее отключение соединения, т. Е. сигнализирует, что он больше не будет отправлять какие-либо данные внутри соединения, но все еще может получать данные. Для достижения этого вам необходимо использовать Shutdown с аргументом Send после завершения отправки.