0

I'm trying to read a response from a third-party, socket based API (Fishbowl) and when I try to read what is returned my project freezes. I'm able to connect, send a request, and close the connection without error.

To test my code I created my own basic server app and my client app works as expected with it. It just doesn't work when I try that same client project against the third-party API.

Any ideas what could be causing this?

Here is my code:

Imports System.Net.Sockets
Imports System.Text

Public Class Form1
    Dim VarSocketServer As New TcpClient
    Dim VarNetworkStream As NetworkStream

    Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        VarSocketServer.Connect("127.0.0.1", 28192)
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim VarNetworkStream As NetworkStream = VarSocketServer.GetStream()

        ' Send a msessage/request to the server. This doesn't return errors and appears to work.
        Dim VarClientRequest As String = "{My request is sent in JSON and includes credentials and key}"
        Dim VarSendByte As [Byte]() = System.Text.Encoding.ASCII.GetBytes(VarClientRequest)
        VarNetworkStream.Write(VarSendByte, 0, VarSendByte.Length)
        VarNetworkStream.Flush()

        ' Read the response from the server. This freezes at "VarNetworkStream.Read"
        Dim VarInStream(10024) As Byte
        Dim VarBytesRead = VarNetworkStream.Read(VarInStream, 0, VarInStream.Length)
        Dim VarDataFromServer As String = System.Text.Encoding.ASCII.GetString(VarInStream)
        VarNetworkStream.Flush()

        Console.WriteLine(">> Data from server: " + VarDataFromServer)
       Console.ReadLine()
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        VarSocketServer.Close()
        Me.Close()
    End Sub
End Class
Visual Vincent
  • 18,045
  • 5
  • 28
  • 75
ptownbro
  • 1,240
  • 3
  • 26
  • 44
  • If it freezes at `VarNetworkStream.Read()` that means that the server hasn't sent any data. `NetworkStream.Read()` blocks until some data has been received or the connection has been terminated. You would have to consult the API's documentation to see if you're missing anything or, if everything seems in order, contact the people responsible for the service/API and explain your problem to them. – Visual Vincent Aug 19 '19 at 06:46
  • Is there a way to check if data is sent so I code against it freezing? – ptownbro Aug 19 '19 at 14:45
  • There is, but the server might also take a small amount of time to send the data so I wouldn't recommend that. Rather, you should set the [`ReadTimeout` property](https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.networkstream.readtimeout?view=netframework-4.8) to the amount of milliseconds you want to wait for data before it'll throw an exception and stop reading. – Visual Vincent Aug 19 '19 at 17:48
  • Also, note that all data might not fit into a single `Read()` call. You might receive less than expected and therefore need to call `Read()` again. Since you're reading a string, you should keep reading bytes until you find a byte with value `0`, which denotes the end of the string, and only after that decode the byte array to a string. – Visual Vincent Aug 19 '19 at 17:48
  • Ok. I will try and report back if needed. Thanks for your help. – ptownbro Aug 20 '19 at 01:14
  • Some more info on this. Could this be related to Endiannes? If so, how would I able that in my code above – ptownbro Sep 06 '19 at 06:16
  • No. Endianness determines how integers are stored in memory. You're working with strings, in which case it is _encoding_ that determines how they are stored (you've chosen to use ASCII, which should be fine for most characters unless the server for some reason uses UTF-16 or higher - but that's unlikely). Are you still having trouble getting it to work? Still not receiving any data? – Visual Vincent Sep 06 '19 at 09:15
  • Yes. I'm still having trouble. I found some sample code in c# and it is using some custom classes and applying Endianness. Somehow it works, but I'm hesitant to use it because it's overly complex and afraid of not being to fix problems that ocurr. – ptownbro Sep 12 '19 at 02:37
  • If you still know the source, please send it and I can inspect the code to see what it does different. I still find it odd, though, that your simple piece of code (which should work) does not receive _any_ data. By the way, try removing every instance of `VarNetworkStream.Flush()` in your code and just see what happens. – Visual Vincent Sep 12 '19 at 08:40
  • Actually by checking the .NET source code I just found out that `NetworkStream.Flush()` does nothing, so you might as well remove it altogether. || What happens if you try using `Encoding.UTF8` instead of `Encoding.ASCII` for both sending and receiving? Also, why are you calling `Console.WriteLine` and `Console.ReadLine` in a Windows Forms application? – Visual Vincent Sep 12 '19 at 08:53
  • I try what you suggested. In the meantime.. The sample code is located at the link below. Remember you asked for it =) Again there is a lot there and https://www.fishbowlinventory.com/developer-network/tools/ – ptownbro Sep 13 '19 at 02:44
  • Are you programming against the Fishbowl API? If so, you should have mentioned that from the beginning as I could have researched it back then. Based on the source code you sent I see it has implemented a certain protocol for handling communication. The reason the C# code works is because it follows this protocol, and the fact that your code doesn't _might_ be why you don't receive any data. – Visual Vincent Sep 13 '19 at 08:52
  • The protocol works by first sending the length of the string data as a big endian, 1-7 bit integer, then it sends the actual string. This allows either side of the API to know exactly how much data will be received from the endpoint. You need to follow this protocol, otherwise you won't be able to communicate with the API properly. What I suggest you do is that you take the C# sample code (except `Program.cs`), put it in a Class Library project and compile it to a DLL. Then you reference that DLL from your VB.NET project and you'll be able to use all its classes from VB.NET. – Visual Vincent Sep 13 '19 at 08:55

0 Answers0