VB.Net - NetworkStream在VBCrLf之后停止发送

时间:2015-08-06 19:07:54

标签: vb.net networkstream

我正在尝试通过TCP发送一个字节数组。它以字符串形式开始(可能长达数千行),转换为字节数组,然后发送给客户端。

我的问题是客户端以突发方式接收数据作为单独的事件,但处理它的子例程需要一次性查看所有数据。为了对此进行限制,我开始使用分隔符编程而不是换行符,但是在其他地方出现了一系列问题,因此我没有对绑带进行绑定,而是认为我会回到根本问题并寻求你的建议。

我怀疑这个问题与网络流有关,也许是由于缺乏缓冲区,它决定了它自己何时分解数据。我试图实现BufferStream,但我陷入了失败之中。

字符串看起来像这样(原谅奇怪的格式,我有很多被SO误解的分隔字符):

  

GamePreloadedVariables Classic 10000 Grain~Forestry~Coal~Silver~Gold~Market Mutual~~~~~~~~ 128,128,0~0,100,0~64,64,64~192,192,192~255,255,0~255,224,192 ~~~~~~~~ 100~100~100~100~100~100 {120 {1}} True`False

     

0 5 5 Dividend 5 Market Mutual {100 {1}} {100 {1}}×100

     

1 100 5 100 1 100 {105 {1}} {100 {1}} 101

     

2 Up 20 {{1} {0 {1}} {105 {1}} {100 {1}} 97

     

...等

最初收到的内容只是第一行:

  
    

GamePreloadedVariables Forestry 10000 100 128,128,0~0,100,0~64,64,64~192,192,192~255,255,0~255,224,192 ~~~~~~~~ 100 {120 {1}} True`False

  

所以我的问题是,是否可以重新设计数据的发送方式,以便包含换行符以及后续行,以便在单个事件中接收整个字符串,无论多长?

以下是我认为需要修改代码的子程序:

100

以下是接收和解释所有传入消息的客户端代码(截断为仅显示相关代码)。

Down

这是有希望的,也许是显而易见的,目前我已经掌握了。想法?

1 个答案:

答案 0 :(得分:0)

为了降低复杂性,我可能会使用阻塞I / O并将整个客户端序列放入后台工作程序或线程中。在那里,只需循环ReadLine()直到流关闭并返回反序列化的游戏对象。

或者,从网络数据包复制到缓冲区或队列中并检查换行符。如果找到,请从缓冲区中删除现在完整的行。然后等待下一个数据包。

您可以将此作为一个起点,而不是异步地等待数据包,它只是读取,直到流结束并使用完成的字符串。

Module TcpListener

    Sub Main()
        Dim Client As New Net.Sockets.TcpClient(New Net.IPEndPoint(Net.IPAddress.Any, 0))
        Client.Connect("server.example.com", 80)
        Read(Client)
    End Sub

    Sub Read(Client As Net.Sockets.TcpClient)
        Dim MessageBuilder As New System.Text.StringBuilder()
        Using Writer As New IO.StreamWriter(Client.GetStream())
            Writer.WriteLine("GET / HTTP/1.1")
            Writer.WriteLine("Host: server.example.com")
            Writer.WriteLine("Connection: close")
            Writer.WriteLine("")
            Writer.Flush()
            Using Stream As New IO.StreamReader(Client.GetStream, False)
                Do
                    Dim Line As String = Stream.ReadLine()
                    ' Stop reading on End of Stream
                    If Line Is Nothing Then Exit Do
                    MessageBuilder.AppendLine(Line)
                Loop
            End Using
        End Using
        Dim Message As String = MessageBuilder.ToString()
        If Message.Length = 11 Then
            'irrelevant code
        ElseIf Message.Length > 100 Then
            Dim ContentChecker As String = Message.Substring(0, 22)
            If ContentChecker = "GamePreloadedVariables" Then
                Load_Preloaded_file(Message)
            End If
        Else
            'irrelevant code
        End If
    End Sub

    Sub Load_Preloaded_file(message As String)
        Console.Write(message)
    End Sub
End Module

对于此示例,我连接到本地Web服务器并对索引页面执行了简单请求。如果它将以“GamePreloadedVariables”开头,它将打印出HTTP协议和内容。重要的是服务器关闭连接,否则循环不会结束。

从这里开始,网络代码还有很长的路要走,即客户端应该是出于性能原因而关闭连接的客户端,可以使用异步调用或单独的线程等。