tcpclient getstream - zero bytes read - vb.net

I have a tcpclient connection setup capturing a continuous http stream. For some reason after the first few bytes are read, the stream does not get any data for a long time. Is there a problem with my code?
Dim tclient As TcpClient = New TcpClient(url, "80")
nstream = tclient.GetStream()
If nstream.CanRead Then
defaultsize = 8000, BUFFER_SIZE = 1024
Dim bufferread(defaultSize) As Byte
Dim data As String
mstring = New StringBuilder
numbytesread = 0
Dim timestamp As DateTime = DateTime.Now
Do
numbytesread = nstream.Read(bufferread, 0, BUFFER_SIZE)
If numbytesread > 1 Then
timestamp = DateTime.Now
data = Encoding.UTF8.GetString(bufferread, 0, numbytesread)
parsingUtilities.appendXMLtoFile(data)
End If
If DateTime.Now.Subtract(timestamp).TotalSeconds > 60 Then
'timestamp shows no bytesread for more than 60 seconds, then reconnect
Exit Sub
End If
Loop While tclient.Connected
End If

Firstly, you absolutely should not read character data in this way. You're assuming that your byte array always contains a whole number of characters. You should use a StreamReader instead, which is designed to handle this.
If you absolutely must read directly from the stream, use a single instance of Decoder which can handle these partial characters, buffering them for the next conversion.
Now, you're also requiring that numbytesread > 1 - what if it's exactly 1? Why would you want to ignore that?
It's also not clear what your timestamp is for... isn't the stream going to block indefinitely until it gets some data? Or have you explicitly set it up with a read timeout?

Related

Reading a filestream issue

I am trying to read a file from my computer and output its contents into a literal control. It gives the error : Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection. This is my first time using FileStream and I'm not 100% about all of the syntax for VB, or if there's even a community-preferred way of reading from a file, but could somebody help me out with this error?
This is the code:
Using fs As New FileStream(_path, FileMode.Open, FileAccess.Read)
Try
Dim fileLength As Integer = CInt(fs.Length)
Dim buffer() As Byte = New Byte() {fileLength}
Dim count As Integer
Dim sum As Integer = 0
While ((count = fs.Read(buffer, sum, fileLength - sum)) > 0)
sum = sum + count
End While
litOutput.Text = buffer.ToString()
Catch ex As Exception
'TODO: log error
End Try
End Using
This line is wrong
Dim buffer() As Byte = New Byte() {fileLength}
It declares an array of 1 byte in which you try to store the length of your file. Probably you have Option Strict set to Off and thus you could go away without noticing immediately the problem.
Of course, if your file is of a reasonable length and it is a simple textfile then there is no need for this loop. Just use File.ReadAllText or File.ReadLines or File.ReadAllLines, and by the way, your code read all your data in a single call because the last parameter of FileStream.Read is the quantity of bytes to read from file and the expression fileLength - sum produces a request to read all the bytes in a single call
Instead if you want to read your file in chunks of certain sizes then
probably you need
Using fs As New FileStream(path, FileMode.Open, FileAccess.Read)
Try
Dim chunkSize = 2000
Dim fileLength As Integer = CInt(fs.Length)
Dim buffer(fileLength) as Byte
Dim blockSize(chunkSize) as Byte
Dim count As Integer = -1
Dim pos As Integer = 0
While count <> 0
count = fs.Read(blockSize, 0, chunkSize-1)
Array.Copy(blockSize, 0, buffer, pos, count)
pos += count
End While
litOutput.Text = Encoding.UTF8.GetString(buffer)
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Using
Notice that this code assumes that your file is a Text file with UTF8 encoding.
It this is not the case then you could try with Encoding.ASCII.GetString or Encoding.Unicode.GetString

Issue sending big string over TCP

I have the following function to send and receive data it works OK for short strings like 150 bytes, but with a string of 2500 bytes it get stuck.
I tried to send some data with HTWin and nothing get the other end of the net.
So receiver on the other end never get even a character.
I tried also with the old Hyperterminal with same result.
Private Function SendReport(ByVal Msg As String, ByVal Host As String, ByVal Port As String) As String
Try
Dim Tx As New TcpClient()
Dim stream As NetworkStream = Nothing
Dim CloseStream As Boolean = False
Dim LingerMode As New LingerOption(True, 5)
' String to store the response ASCII representation.
Dim responseData As [String] = [String].Empty
Tx.NoDelay = True
Tx.LingerState = LingerMode
Tx.SendTimeout = 10000
Tx.ReceiveTimeout = 10000
Tx.Connect(Host, Port)
' Translate the passed message into ASCII and store it as a Byte array.
Dim data As [Byte]() = System.Text.Encoding.ASCII.GetBytes(Msg)
' Get a client stream for reading and writing.
' Stream stream = client.GetStream();
stream = Tx.GetStream()
CloseStream = True
'stream.WriteTimeout = 100
' Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length)
'Tx.Connected
' Receive the TcpServer.response.
' Buffer to store the response bytes.
data = New [Byte](256) {}
' Read the first batch of the TcpServer response bytes.
Dim bytes As Int32 = stream.Read(data, 0, data.Length)
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes)
If CloseStream = True Then
stream.Close()
End If
Tx.Close()
Return responseData
Catch ex As Exception
WriteRTBLog(ex.Message, Color.Red)
WriteRTBLog(ex.StackTrace, Color.DarkRed)
Return "Error"
End Try
End Function
If I split the big string into smaller one and call this function over and over all the data reach the other end.
Also, I need to get an ACK packet that is big too and the code must wait for and special character that indicates the end.
I was thinking in to create a Thread with a TcpListener but, Is possible to have a TcpListener in the same port of a TcpClient?
The whole idea is to send a big string that is separated by an special character and finished with another special character.
The other end receive the data, split the string using the first special character and send one ACK by every item in the split function.
And in the last ACK send the second special character to indicate the end of the communication, so my application can process the received data properly.
I think I'm drowning in a glass of water.

Sending multiple hex in array of bytes instead

I have problem about socket to send multiple hex in one send to socket
Here the detail :
Private Sub sendACK()
Dim msgACK As String
Dim sendBytes As Byte()
tmpStr = ""
list.Clear()
msgACK = "33CC"
For j = 1 To Len(msgACK)
list.Add(Mid(msgACK, j, 2))
j += 1
Next
For Each tmpStr In list
sendBytes = HexToBytes(tmpStr)
clientSocket.BeginSend(sendBytes, 0, sendBytes.Length, SocketFlags.None, New System.AsyncCallback(AddressOf OnSend), clientSocket)
Next
End Sub
Public Function HexToBytes(ByVal s As String) As Byte()
Dim bytes As String() = s.Split(" "c)
Dim retval(bytes.Length - 1) As Byte
For ix As Integer = 0 To bytes.Length - 1
retval(ix) = Byte.Parse(bytes(ix), System.Globalization.NumberStyles.HexNumber)
Next
Return retval
End Function
Private Sub OnSend(ByVal ar As IAsyncResult)
clientSocket = ar.AsyncState
clientSocket.EndSend(ar)
Thread.Sleep(100)
End Sub
==> List as arraylist
That code will be result :
Socket send 33
end send
Socket send CC
end send
============================
The program should be sending in one time like this :
Socket send 33 CC
end send
============================
is there any idea about convert string "33CC" into byte and then that program just sending 1 time in outter "for each" ?
thanks for reading and answering....
GBU
Your assumption is incorrect. It does indeed send both bytes at once. You are only calling BeginSend once and you are giving it both bytes, so if it is receiving them at all on the other end, then it is indeed sending them. In fact, there is no difference at all between sending them individually or sending them together. Since the socket works as a stream, the length of time between each byte being sent is largely irrelevant. There will be no way on the receiving end to know whether the two bytes were sent together or separately. All the receiving end will know is that the two bytes were sent in that order. If you think they are being sent as two separate "sends" on the receiving end, it sounds like you are making some invalid assumptions about how to read the data from the socket.
However, I should mention that the way you are sending the bytes, by first creating a hex string and then parsing it, is a bit silly. If you need to parse it as a string, because you are reading the hex values from a text file, or something, that's fine, but otherwise, you should just use hex byte literals in your code rather than strings, for instance:
Dim sendBytes As Byte() = {&H33, &HCC}

SSRS Decrypting database column throws error "Value cannot be null. Parameter name: inputBuffer"

We have a database field that is encrypted in a C# MVC app using Entity Framework. That part works fine for encrypting and decrypting. We need to show this data decrypted in an SSRS report.
I've taken the Decrypt method and converted it to VB.Net and placed in the code behind of the report. The error occurs when calling the StreamReader's ReadToEnd method. We've found some references online about there being an issue trying to close a stream that's already closed. This stream is only being read from one time and we're reading the entire stream so it should not be closed at that point.
I tried reading Length - 1 bytes from the cryptoStream and that did not throw an error. If I try to read Length bytes, I get the same error. If I read all but one byte and then read only the last byte I get the same error. Stack trace and code are below. Any help would be greatly appreciated.
Stacktrace:
at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
at System.Security.Cryptography.CryptoStream.FlushFinalBlock()
at System.Security.Cryptography.CryptoStream.Dispose(Boolean disposing)
at System.IO.Stream.Close()
at System.IO.Stream.Dispose()
at ReportExprHostImpl.CustomCodeProxy.Decrypt(String ciphertext)
Code:
public function Decrypt(byval ciphertext as string) as string
dim message as string
dim key as string
dim saltSize as integer
saltsize = 32
key = "KEYGOESHERE"
dim allTheBytes as byte()
allTheBytes = Convert.FromBase64String(ciphertext)
dim saltBytes as byte()
saltBytes = new byte(saltsize) {}
dim ciphertextBytes as byte()
ciphertextBytes = new byte(allTheBytes.Length - saltSize) {}
dim i as integer
for i = 0 to saltsize - 1
saltBytes(i) = allTheBytes(i)
next i
for i = saltSize to (allTheBytes.Length - 1)
ciphertextBytes(i - saltSize) = allTheBytes(i)
next i
try
using keyDerivationFunction as System.Security.Cryptography.Rfc2898DeriveBytes = new System.Security.Cryptography.Rfc2898DeriveBytes(key, saltBytes)
dim keyBytes as byte()
keyBytes = keyDerivationFunction.GetBytes(32)
dim ivBytes as byte()
ivBytes = keyDerivationFunction.GetBytes(16)
using aesManaged as System.Security.Cryptography.AesManaged = new System.Security.Cryptography.AesManaged()
aesManaged.Padding = System.Security.Cryptography.PaddingMode.PKCS7
aesManaged.Mode = System.Security.Cryptography.CipherMode.CBC
using decryptor as System.Security.Cryptography.ICryptoTransform = aesManaged.CreateDecryptor(keyBytes, ivBytes)
using memoryStream as System.IO.MemoryStream = new System.IO.MemoryStream(ciphertextBytes)
using cryptoStream as System.Security.Cryptography.CryptoStream = new System.Security.Cryptography.CryptoStream(memoryStream, decryptor, System.Security.Cryptography.CryptoStreamMode.Read)
using streamReader as System.IO.StreamReader = new System.IO.StreamReader(cryptoStream)
message = streamReader.ReadToEnd()
return message
end using
end using
end using
end using
end using
end using
catch e as Exception
return e.StackTrace
end try
end function
This sounds like a padding error. First of all, AES in CBC mode requires an exact message size for decryption, N times the blocksize (of 16 bytes). If the message has this size then AES CBC ciphertext will always decrypt. Any other problem can only be related to padding really. So what happens is that the last deciphered plain text does not have the correct padding, and an exception occurs.
Now comes the fun part; this error occurs when:
the binary AES key is not identical;
if the algorithm or mode is incorrect or if the wrong padding algorithm is used;
if one of the last two blocks is mangled;
if the last part of the encryption is missing in action.
In other words, if something is wrong, it is likely that it will turn up during the removal of the padding bytes. If you are unlucky, the last incorrect block still ends with a byte value of 01 hexadecimal, and padding succeeds, showing that padding is no substitution for integrity protection.

BeginReceive trailing Null character/chr(0)

I'm coding an ascynchronous socket client for transferring files (following this Microsoft article) and notice that using BeginReceive corrupts the transfer because it adds a single Null character/chr(0) at the end of each packet. What could be causing this issue? I thought it might be the sending side, but I tested it with SendFile and had the same result.
In the Microsoft article it converts the bytes to an ASCII string and appends it to a StringBuilder. I want to save the bytes on-the-fly, so I barely modified the ReceiveCallback like so:
Private Shared Sub ReceiveCallback(ByVal ar As IAsyncResult)
Dim state As StateObject = CType(ar.AsyncState, StateObject)
Dim client As Socket = state.workSocket
Dim bytesRead As Integer = client.EndReceive(ar)
If bytesRead > 0 Then
FileIO.FileSystem.WriteAllBytes(Application.StartupPath & "\test.exe", state.buffer, True)
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReceiveCallback), state)
Else
receiveDone.Set()
End If
End Sub
The problem is a misconception on how Receive, or BeginReceive & EndReceive work.
When you call Receive and give it a buffer and a size, you are specifying the maximum amount of data to receive. It is the bytesRead that tells you how much you actually received. You need to only write that number of bytes to your output file, as only that portion of your buffer was populated with data.
See here for more details:
http://msdn.microsoft.com/en-us/library/w3xtz6a5