我正在尝试模拟与现有服务器通信的客户端程序。我使用过wireshark,可以看到来回的消息。客户端程序-连接并发送一个字符串
9 0 0 99 3 0 CR LF
CLIENT SEND
0.001157 192.168.0.210 192.168.0.197 TCP 69 61517 → 22223 [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
服务器以确认字符和返回文本消息响应,然后是CRLF
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,确认字符]只是一个[PSH,确认字符],服务器没有响应。在我的实验中,我发现如果我在写入服务器后关闭流,我可以在wireshark上看到响应是send(但是现在链接关闭了,所以我无法获得它)有人知道如何在保持连接存活的同时生成[FIN,PSH,确认字符]吗??
我的发送消息例程
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:{" & GetModuleName(er) & "}" & Information.Err().Number & " Mess:" & er.Message)
End Try
End If
Catch er As Exception
DisplayLog("ERROR Module:{" & GetModuleName(er) & "}" & Information.Err().Number & " Mess:" & er.Message)
End Try
End Sub
我认为你对TCP的工作方式有错误的期望。FIN不是某些消息的结束,而是完整连接的结束。因此,它是在您关闭流时发送的,而不是在消息之后发送的。
TCP根本不提供任何类型的消息语义学,它只是一个字节流。如果你需要消息语义学,你不能通过在现有连接中任意多次发送FIN来将这些消息添加到TCP,但是你必须在TCP的基础上逐流添加这些消息语义学。典型的方法是在消息前面加上长度或有某种消息结束标记(如CRLF基于文本的协议)。