-1

I'm trying to transmit data through the stream in Visual Basic .NET I try the next:

Client:

tcpclnt = New TcpClient()
tcpclnt.Connect("127.0.0.115", 40000)
clientstream = tcpclnt.GetStream()

 Dim I As Integer
 Dim msg() As Byte
 For I = 1 To 1000
     msg = BitConverter.GetBytes(I) ' HERE IS THE PROBLEM
     clientstream.Write(msg, 0, msg.Length)
 Next

Server:

Public Shared bytes(1024) As Byte
Public Shared data As String = Nothing

Server = New TcpListener(IPAddress.Any, 40000)
Server.Start()
' ... some server routine

Dim serverstream As NetworkStream = myClient.GetStream()
Dim i As Int32
i = serverstream.Read(bytes, 0, bytes.Length)
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i)
Invoke(Sub() TextBox3.Text = "Received: " + data)

The problem is: to get data from stream it have to be Byte() type. So to put data to stream it also have to be in Byte(). But I want to transmit integers (1000 for example). It converts in 4 bytes and when server reads it he takes four different symbols, not the number 1000!

Instead of 1000 I got two spaces.

Mikhail_Sam
  • 10,602
  • 11
  • 66
  • 102
  • 2
    You have to use `BitConverter.ToInt32` server-side. Note that the code will be a little more complex than what you wrote, because there is no guarantee that `Read()` will return the number of bytes you requested, because for example a TCP packet could be split in two. – xanatos Mar 27 '17 at 13:54
  • Like @xanatos says, since TCP is a stream-based protocol the application layer has no knowledge of where data begins or ends. If you want to send other data than strings you should look into [**message framing**](http://stackoverflow.com/questions/37341382/c-sharp-deserializing-a-struct-after-receiving-it-through-tcp/37352525#37352525). – Visual Vincent Mar 27 '17 at 15:20
  • As a side note: it's unnecessary to include the language in the title of the question. Stack Overflow's tag system ensures all that will be handled properly. See this for more info: [**Should questions include "tags" in their titles?**](https://meta.stackexchange.com/questions/19190/) – Visual Vincent Mar 27 '17 at 15:27
  • @VisualVincent your comments are useful as always! Thank you! I edited title of my question. And now I'm reading about message farming! – Mikhail_Sam Mar 28 '17 at 06:31

2 Answers2

1

You have to use BitConverter.ToInt32 server-side. Note that the code will be a little more complex than what you wrote, because there is no guarantee that Read() will return the number of bytes you requested, because for example a TCP packet could be split in two (see for example this response).

The code should be:

Dim ix As Integer = 0
Dim bytes As Byte() = New Byte(3) {}

While ix < bytes.Length
    Dim read As Integer = serverstream.Read(bytes, ix, bytes.Length - ix)
    ix += read
End While

Dim i As Integer = BitConverter.ToInt32(bytes, 0)
Community
  • 1
  • 1
xanatos
  • 109,618
  • 12
  • 197
  • 280
  • 3
    Actually the array declaration should be `Dim bytes As Byte() = New Byte(4 - 1) {}`. In VB.NET you specify the upper bound of the array rather than the size. Therefore `New Byte(4)` will have a size of 5, because it reserves index 0-4. – Visual Vincent Mar 27 '17 at 15:23
0

Thank you for the perfect answer, @xanatos. I find one more way and use it, so I want to post it too.

I used this way:

 For I = 1 To 1000
        msg = Encoding.UTF8.GetBytes(Convert.ToString(I))
        clientstream.Write(msg, 0, msg.Length)
 Next

I suppose your solution is better in the way of controlling packages and I will use it for transmitting numeric data, but for my current case I used my solution.

Mikhail_Sam
  • 10,602
  • 11
  • 66
  • 102