Search code examples
vb.netstreamserver-sent-events

Stream does not end


I try to write a Client that consumes a Server-Sent-Event using this code:

Public Shared Function OpenSSEStream(ByVal url As String, ByVal _token As String, ByVal _identifier As String, ByVal _environment As String) As Stream
    Dim request = WebRequest.Create(New Uri(url))
    CType(request, HttpWebRequest).AllowReadStreamBuffering = False
    request.Headers.Add("Authorization:Bearer " + _token)
    request.Headers.Add("environment:" + _environment)
    request.Credentials = New NetworkCredential("id", _identifier)
    Dim response = request.GetResponse()
    Dim stream = response.GetResponseStream()
    SSEApplication.ReadStreamForever(stream)
    Return stream
End Function

Public Shared Sub ReadStreamForever(ByVal stream As Stream)
    Dim encoder = New UTF8Encoding()
    Dim buffer = New Byte(2047) {}

    While True
        If stream.CanRead Then
            Dim len As Integer = stream.Read(buffer, 0, 2048)
            If len > 0 Then
                Dim text = encoder.GetString(buffer, 0, len)
            End If
        End If
    End While
End Sub

This works great so for, I can see the text from the server (in debug mode) in the text Variable. Unfortunately, if I run the code (not debugging) I get in Break Mode. I can see in Debug Mode that the text file is filled with about 2000 datasets and it looks like the stream does not end and runs into an endless loop or so? Can anyone help me here?


Solution

  • You need to exit the loop, there's nothing right now that tells it to exit.

    While True
        If stream.CanRead Then
            Dim len As Integer = stream.Read(buffer, 0, 2048)
            If len > 0 Then
                Dim text = encoder.GetString(buffer, 0, len)
            Else
                Exit While
            End If
        Else
            Exit While
        End If
    End While
    

    Also, a stream can receive the information only in pieces. You should concatenate the data.

    Dim text As String = ""
    
    While True
        If stream.CanRead Then
            Dim len As Integer = stream.Read(buffer, 0, 2048)
            If len > 0 Then
                text &= encoder.GetString(buffer, 0, len)
            Else
                Exit While
            End If
        Else
            Exit While
        End If
    End While
    

    This can all be refactor

    Dim streamData As New StringBuilder
    
    While stream.CanRead
        Dim len As Integer = stream.Read(buffer, 0, 2048)
    
        If len > 0 Then
            ' There is the possibility that a Unicode character be split
            streamData.Append(encoder.GetString(buffer, 0, len))
        Else
             Exit While
        End If
    End While