How do I convert the following line of code from VB.NET to C#.
Dim bytes(tcpClient.ReceiveBufferSize) As Byte
I got the following line from the developerfusion web site, but it's giving me wrong results in my program.
byte[] bytes = new byte[tcpClient.ReceiveBufferSize + 1];
Here is an example of my entire code in Visual Basic.
Dim tcpClient As New System.Net.Sockets.TcpClient()
TcpClient.Connect(txtIP.Text, txtPort.Text)
Dim networkStream As NetworkStream = TcpClient.GetStream()
If networkStream.CanWrite And networkStream.CanRead Then
Dim sendBytes As [Byte]() = Encoding.ASCII.GetBytes(txtSend.Text.Trim())
networkStream.Write(sendBytes, 0, sendBytes.Length)
' Read the NetworkStream into a byte buffer.
TcpClient.ReceiveBufferSize = 52428800 '50 MB
'Do I need to clean the buffer?
'Get the string back (response)
Dim bytes(tcpClient.ReceiveBufferSize) As Byte
networkStream.Read(bytes, 0, CInt(TcpClient.ReceiveBufferSize))
' Output the data received from the host to the console.
Dim returndata As String = Encoding.ASCII.GetString(bytes)
Visual Basic specifies the maximum bound of the array instead of the length of the array (arrays start at index 0), so your conversion added an extra byte. In your code however the correct way would be:
byte[] bytes = new byte[tcpClient.ReceiveBufferSize];
If you get wrong results, tell us what exactly is wrong. Maybe it's another part of the code.
Edit: Remove the \0 like this:
byte[] bytes = new byte[tcpClient.ReceiveBufferSize];
int bytesRead = networkStream.Read(bytes, 0, tcpClient.ReceiveBufferSize);
// Output the data received from the host to the console.
string returndata = Encoding.ASCII.GetString(bytes,0,bytesRead);
Edit: Even better to read the data in packets, so you don't need to reserve a large buffer upfront:
byte[] bytes = new byte[4096]; //buffer
int bytesRead = networkStream.Read(bytes, 0, bytes.Length);
while(bytesRead>0)
{
// Output the data received from the host to the console.
string returndata = Encoding.ASCII.GetString(bytes,0,bytesRead);
Console.Write(returndata);
bytesRead = networkStream.Read(bytes, 0, bytes.Length);
}
Related
I tried to send Hex bytes through the TCP using VB.net. And receive the response of data.
Following code I used,
Dim tcpClient As New System.Net.Sockets.TcpClient()
tcpClient.Connect("192.168.1.10", 502)
Dim networkStream As NetworkStream = tcpClient.GetStream()
If networkStream.CanWrite And networkStream.CanRead Then
' Do a simple write.
Dim sendBytes As [Byte]() = {&H0, &H4, &H0, &H0, &H0, &H6, &H5, &H3, &HB, &HD3, &H0, &H1}
networkStream.Write(sendBytes, 0, sendBytes.Length)
' Read the NetworkStream into a byte buffer.
Dim bytes(tcpClient.ReceiveBufferSize) As Byte
networkStream.Read(bytes, 0, CInt(tcpClient.ReceiveBufferSize))
' Output the data received from the host to the console.
Dim returndata As String = Encoding.ASCII.GetString(bytes)
TextBox1.Text = ("Host returned: " + returndata)
Else
If Not networkStream.CanRead Then
TextBox1.Text = "cannot not write data to this stream"
tcpClient.Close()
Else
If Not networkStream.CanWrite Then
TextBox1.Text = "cannot read data from this stream"
tcpClient.Close()
End If
End If
End If
When I send sendbytes data, I did not get any data. When I send data, master automatically sends me data but I did not get any data. This is Modbus communication.
I can only see Host returned:
The data is there, but you cannot see it because it starts with a null byte (&H0 or just 0). Most text controls that encounter a null byte interprets that as the end of the string and thus doesn't render the rest of the text.
GetString() merely takes the bytes as is and converts them into the respective chars with the same values. It is up to you to turn the result into a readable format.
The solution is to skip GetString() and instead iterate the array, converting every byte into a hex or number string.
Also, two very important things:
You shouldn't use TcpClient.ReceiveBufferSize in your code as it is used for the internal buffer. You should always decide the buffer size on your own.
Since TCP is a stream-based protocol the application layer has no notion of packets. One 'send' from the server usually does not equal one 'receive'. You might receive more or less data than what the first packet actually is. Use the return value from NetworkStream.Read() to determine how much has been read.
You then need to read up on the Modbus documentation and see if its data contains something that indicates the end or the length of a packet.
'Custom buffer: 8 KB.
Dim bytes(8192 - 1) As Byte
Dim bytesRead As Integer = networkStream.Read(bytes, 0, bytes.Length)
Dim returndata As String = "{"
'Convert each byte into a hex string, separated by commas.
For x = 0 To bytesRead - 1
returnData &= "0x" & bytes(x).ToString("X2") & If(x < bytesRead - 1, ", ", "}")
Next
TextBox1.Text = "Host returned: " & returnData
I am writing a program in VB.net that is connecting to a server, sending a byte array to the server and then receives a byte array as an answer then needs to receive a continuous stream of bits from the server.
The Sent Bit Array is 84 bytes and should be the same the first time it is received from the server and vary in size every time the server sends it back after that.
the start and the end of the message will always be the same but the size of the bit array sent will vary.
My issue is that I can write the bits to the server but I am not able to receive any of the follow-on bits that are broadcast.
Any suggestions
Public Sub connect(TcpClient As TcpClient)
Dim NetworkStream As NetworkStream = TcpClient.GetStream()
If networkStream.CanWrite And networkStream.CanRead Then
' Do a simple write.
Dim sendBytes As [Byte]() = IO.File.ReadAllBytes(startupFile)
networkStream.Write(sendBytes, 0, sendBytes.Length)
' Read the NetworkStream into a byte buffer.
Dim bytes(1024) As Byte
NetworkStream.Read(bytes, 0, bytes.Length)
' Output the data received from the host to the console.
Dim returndata As String = Encoding.ASCII.GetString(bytes)
Dim fileWrite As New IO.StreamWriter(writeFile)
fileWrite.Write(returndata)
fileWrite.Close()
Else
If Not networkStream.CanRead Then
Console.WriteLine("cannot not write data to this stream")
TcpClient.Close()
Else
If Not networkStream.CanWrite Then
Console.WriteLine("cannot read data from this stream")
TcpClient.Close()
End If
End If
End If
End Sub
I'm trying to familiarize myself with network programming, and what better place to start than designing an FTP client code library?
So far I'm not doing very good. I'm trying to create a method which downloads a file from a remote server to a local file path. To do so, all the examples that I could find declare a byte array that serves as a data buffer. I completely understand the point of doing that, rather than reading and writing byte per byte, but I just can't get it to work. Whenever I set a buffer greater than 1 byte, the output is somehow corrupted (different checksums, media files won't play etc).
Can someone please point out what I'm doing wrong here:
Public Function DownloadFile(source As Uri, output As Uri) As FtpStatusCode
Dim request = FtpWebRequest.Create(source)
request.Method = WebRequestMethods.Ftp.DownloadFile
Using response As FtpWebResponse = CType(request.GetResponse, FtpWebResponse)
Using outputStream = New FileStream(output.AbsolutePath, FileMode.Create)
Do
Dim buffer(8192) As Byte
response.GetResponseStream.Read(buffer, 0, buffer.Length)
outputStream.Write(buffer, 0, buffer.Length)
Loop While outputStream.Position < response.ContentLength
End Using
Return response.StatusCode
End Using
End Function
Because this code does work when I set the buffer size to 1, I feel like there's something going wrong with the byte order. But all of this code is synchronous, so how is that even possible...
EDIT
I got it to work now, so here's the code solution for future reference (thanks again #tcarvin):
Public Function DownloadFile(source As Uri, output As Uri) As FtpStatusCode
Dim request = FtpWebRequest.Create(source)
request.Method = WebRequestMethods.Ftp.DownloadFile
Using response As FtpWebResponse = CType(request.GetResponse, FtpWebResponse)
Using inputStream = response.GetResponseStream
Using outputStream = New FileStream(output.AbsolutePath, FileMode.Create)
Do
Dim buffer(8192) As Byte
Dim buffered = inputStream.Read(buffer, 0, buffer.Length).Read(buffer, 0, buffer.Length)
outputStream.Write(buffer, 0, buffered)
Loop While outputStream.Position < response.ContentLength
End Using
End Using
Return response.StatusCode
End Using
End Function
When reading from a stream, you need to capture the return value of the method. Read returns how many bytes were just read. That is the number of bytes you need to then write to your output stream.
I've got a problem to make two applications to send text-data between themselves.
The message is transmitted without any problems, the answer is received too. But, there is a lot of a "New line" char in the end of the string send/received on each side.
I guess it's because of I'm reading the full buffer; I've tried to remove all Chr(10) and Chr(13); I also tried to trim the string, but it didn't worked.
Here the code I use :
Client Side :
Dim cl As New TcpClient
cl.Connect("127.0.0.1", 2000)
Dim str As NetworkStream = cl.GetStream
Dim HelloInBytes As Byte() = Encoding.UTF8.GetBytes("Hello")
str.Write(HelloInBytes, 0, HelloInBytes.Length)
Dim Buffer(cl.ReceiveBufferSize) As Byte
str.Read(Buffer, 0, cl.ReceiveBufferSize)
Console.WriteLine(Encoding.UTF8.GetChars(Buffer))
Server Side :
Dim srv As New TcpListener(IPAddress.Any, 2000)
srv.Start()
Dim cl As TcpClient = srv.AcceptTcpClient
Dim str As NetworkStream = cl.GetStream
Dim buf(cl.ReceiveBufferSize) As Byte
str.Read(buf, 0, cl.ReceiveBufferSize)
Dim res As Byte() = Encoding.UTF8.GetBytes("World")
str.Write(res, 0, res.Length)
Is there a way to "clean" the received string ?
Thanks for help.
EDIT : Solution :
It Works with Harzcle solution.
I found another solution which is to use this function on the received string :
Public Function CleanString(ByRef Str As String)
Return Str.Replace(Encoding.UTF8.GetChars({0, 0, 0, 0}), Nothing)
End Function
UTF8 works on 4 bytes, and when I read the stream and I put it into a buffer, if there is no char, the 4 bytes stay on a 0 value.
Use Flush() after you write into the buffer
str.Write(HelloInBytes, 0, HelloInBytes.Length)
str.Flush()
And
str.Write(res, 0, res.Length)
str.Flush()
Edit:
You can use a delimiter or something like that.
Client side:
Dim delimiterChar as Char = "|"
Dim out As Byte() = System.Text.Encoding.UTF8.GetBytes(txtOut.Text + delimiterChar)
server.Write(outStream, 0, outStream.Length)
server.Flush()
And Server side:
Dim delimiterChar as Char = "|"
Dim Stream As NetworkStream = clientSocket.GetStream()
Stream.Read(bytesFrom, 0, CInt(client.ReceiveBufferSize))
Dim data As String = System.Text.Encoding.UTF8.GetString(bytesFrom)
data = data.Substring(0, data.IndexOf(delimiterChar)) 'From 0 to delimiter
This will remove all null characters at the end of the received string
client_content = client_content.Replace(Chr(0), Nothing)
To remove new lines:
client_content = client_content.Replace(vbLf, Nothing)
I need to store the first byte of data read from the network stream as a string, so I can call it back later.
prinf(" While 1
Dim tcpListener As New TcpListener(IPAddress.Any, 80) ' Listen to port given
Console.WriteLine("Waiting for connection...")
tcpListener.Start()
'Accept the pending client connection and return 'a TcpClient initialized for communication.
Dim tcpClient As TcpClient = tcpListener.AcceptTcpClient()
Console.WriteLine("Connection accepted.")
' Get the stream
Dim networkStream As NetworkStream = tcpClient.GetStream()
' Read the stream into a byte array
Dim bytes(tcpClient.ReceiveBufferSize) As Byte
networkStream.Read(bytes, 0, CInt(tcpClient.ReceiveBufferSize))
' Return the data received from the client to the console.
Dim clientdata As String = Encoding.ASCII.GetString(bytes)
Console.WriteLine(("Client Sent: " + clientdata))
' Return the data received from the client to the console.
Dim responseString As String = "Hello"
'Dim chat_name As String = "Name"
Dim sendBytes As [Byte]() = Encoding.ASCII.GetBytes(responseString)
networkStream.Write(sendBytes, 0, sendBytes.Length)
Console.WriteLine(("Response: " + responseString))
tcpClient.Close() 'Close TcpListener and TcpClient
tcpListener.Stop()
End While");
Thats my server ^ everything works fine, but I need the 1st piece of data read to be stored, such as if I get "Name" it should be stored in an array
Thanks
You'll need to define exactly what you mean by "1st piece of data" - is this data delimited in some form (like HTTP headers - key/value pairs are delimited by carriage-return line-feed)? Length-prefixed (like HTTP bodies when the Content-Length header is specified)? You almost certainly don't just want the first byte.
If you were hoping to just send the name and then send something else, without any indication of the fact that they're different bits of data, you're going to be disappointed. Streams are just sequences of bytes - there's nothing (built-in) to say "read what the client sent in their first API call".
This should work:
Dim strFirstByte as string = vbNullString
While 1
' ... Your code ...
Dim bytes(tcpClient.ReceiveBufferSize) As Byte
networkStream.Read(bytes, 0, CInt(tcpClient.ReceiveBufferSize))
If strFirstByte = vbNullString Then strFirstByte = bytes(0).ToString("X2")
' ... The rest of your code ...
End While