Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 847
  • Last Modified:

Reading Binary data from a socket connection

I have an application that firstly reads a file into a BinaryReader. That BinaryReader then transmits this over a socket as follows:

Dim socket As New tcpClient()
Dim socketWriter As New IO.StreamWriter(socket.GetStream)
Dim diskFile As FileStream
Dim fileToSend As BinaryReader
Dim iCounter as Integer

        diskFile = New FileStream(fileName, FileMode.Open, FileAccess.Read)
        fileToSend = New BinaryReader(diskFile)

        For iCounter = 1 To System.Convert.ToInt32(diskFile.Length)
                Dim tmpByte As Byte = fileToSend.ReadByte
                socketWriter.Write(tmpByte)
                Console.WriteLine(tmpByte)
        Next iCounter

        socketWriter.Flush()


This works (to the best of my knowledge) fine. Issue I have is how the hell do I read the reverse. I have the following code that I filtched from somewhere but it doesnt work, I always get a file that is 32k which is the size of the obj_SocketState.Buffer byte array (Public Buffer(32767) As Byte):

' CallBack Procedure to accept incoming data from a connected Socket.
    Private Sub onDataArrival(ByVal ar As IAsyncResult)

        Try
            Dim writer As New BinaryWriter(File.Create("C:\test.zip"))
            Dim obj_SocketState As StateObject = CType(ar.AsyncState, StateObject)
            Dim obj_Socket As System.Net.Sockets.Socket = obj_SocketState.WorkSocket
            Dim BytesRead As Integer = obj_Socket.EndReceive(ar)

            If BytesRead > 0 Then
                writer.Write(obj_SocketState.Buffer)
            End If
        Catch e As System.Exception
            Console.WriteLine(e.ToString)
        End Try

    End Sub

Looking forward to any reply...just about :-)

Andrew
0
andrewharris
Asked:
andrewharris
2 Solutions
 
testnCommented:
Try

   Dim writer As New BinaryWriter(File.Create("C:\test.zip"))


   Private Sub onDataArrival(ByVal ar As IAsyncResult)

        Try
            Dim obj_SocketState As StateObject = CType(ar.AsyncState, StateObject)
            Dim obj_Socket As System.Net.Sockets.Socket = obj_SocketState.WorkSocket
            Dim BytesRead As Integer = obj_Socket.EndReceive(ar)

            If BytesRead > 0 Then
                writer.Write(obj_SocketState.Buffer)
            Else
                writer.Close()
            End If
        Catch e As System.Exception
            Console.WriteLine(e.ToString)
        End Try

    End Sub

and you have to change your code so that it will check the number of bytes returned from EndReceive. If it is greater then zero, you have to start another BeginReceive
0
 
krznpskCommented:
You need to close the socketwriter in the server app, as well as flush it.
0
 
andrewharrisAuthor Commented:
testn,

I have uped the points to 500, could you explain your last line, that is that part I am looking for.

krznpsk,

At what point should you flush it? Just before close? Before/After each receive?

Regards

Andrew
0
NFR key for Veeam Backup for Microsoft Office 365

Veeam is happy to provide a free NFR license (for 1 year, up to 10 users). This license allows for the non‑production use of Veeam Backup for Microsoft Office 365 in your home lab without any feature limitations.

 
andrewharrisAuthor Commented:
Ohh....Hang on, you mean do something like this:



Private Sub onDataArrival(ByVal ar As IAsyncResult)

        Try
            Dim obj_SocketState As StateObject = CType(ar.AsyncState, StateObject)
            Dim obj_Socket As System.Net.Sockets.Socket = obj_SocketState.WorkSocket
            Dim BytesRead As Integer = obj_Socket.EndReceive(ar)

            If BytesRead > 0 Then
                writer.Write(obj_SocketState.Buffer)
                obj_Socket.BeginReceive(obj_SocketState.Buffer, 0, obj_SocketState.BufferSize, 0, New AsyncCallback(AddressOf onDataArrival), obj_SocketState)
            Else
                writer.Close()
            End If
        Catch e As System.Exception
            Console.WriteLine(e.ToString)
        End Try

    End Sub

OK, I got that, but I still have this issue of a byte array that is my buffer which is 32767 bytes. If I only receive 32600 bytes I still get a file that is 32767 (32k).

Regards

Andrew
0
 
Bob LearnedCommented:
With the BinaryWriter, you can specify how many bytes to write to the file:

writer.Write(obj_SocketState.Buffer, 0, BytesRead)
0
 
andrewharrisAuthor Commented:
OK, but.... I have a buffer of 32767 bytes. If I only receive (and am only ever going to receive) 32600 bytes, thebuffer is still 32767 bytes. How do I know that I should only write 32600 bytes?

Regards

Andrew
0
 
Bob LearnedCommented:
When you receive 32600 bytes, what is the value of BytesRead?
0
 
andrewharrisAuthor Commented:
Dah!! I am such a moron...

OK I have managed to get it working as a proof of concept doing this at the client:

Dim socket As New tcpClient()
Dim socketWriter As New IO.StreamWriter(socket.GetStream)
Dim diskFile As FileStream
Dim fileToSend As BinaryReader
Dim iCounter as Integer

        diskFile = New FileStream(fileName, FileMode.Open, FileAccess.Read)
        fileToSend = New BinaryReader(diskFile)

        socketWriter.Write(fileToSend.ReadBytes(System.Convert.ToInt32(diskFile.Length)))
        socketWriter.Flush()

Then this on the server:

Private Sub onDataArrival(ByVal ar As IAsyncResult)

Private bytesReceived as Integer

        Try
            Dim obj_SocketState As StateObject = CType(ar.AsyncState, StateObject)
            Dim obj_Socket As System.Net.Sockets.Socket = obj_SocketState.WorkSocket
            Dim BytesRead As Integer = obj_Socket.EndReceive(ar)
            bytesReceived = bytesReceived + BytesRead

            ' The file I am sending is 931 bytes so this works only when the file is this size.
            If bytesReceived < 931 Then
                obj_Socket.BeginReceive(obj_SocketState.Buffer, 0, obj_SocketState.BufferSize, 0, New AsyncCallback(AddressOf onDataArrival), obj_SocketState)
            Else
                writer.Write(obj_SocketState.Buffer, 0, bytesReceived)
                writer.Flush()
                writer.Close()
                obj_Socket.BeginReceive(obj_SocketState.Buffer, 0, obj_SocketState.BufferSize, 0, New AsyncCallback(AddressOf onDataArrival), obj_SocketState)
            End If
        Catch e As System.Exception
            Console.WriteLine(e.ToString)
        End Try


Now the few issues I have are:

1. Figuring the size of the file without sending it
2. writer.Close() doesnt close the file off. I have to exit the application.

If you can answer those then I am done. If not, no biggy I will just post another question. Either way I am going to split the points between testn and TheLearnedOne

Regards

Andrew
0
 
Bob LearnedCommented:
I only see writer.Close when bytesReceived < 931 .  You should probably add a Finally within the Try...Catch to close the Writer.

If the file is written to disk:  
      Dim file As System.IO.FileInfo = New System.IO.FileInfo("<path>")
      dim length As Integer file.Length()

0
 
andrewharrisAuthor Commented:
TheLearnedOne,

In my example, the file I am sending is always 931 and the statement gets executed, but the files is inaccessible until I stop the debug session.

Regards

Andrew
0
 
andrewharrisAuthor Commented:
OK Ignore my last stuff. really just irrelevant tothis question.

Split and away we go.

Thanks again.

Andrew
0

Featured Post

Efficient way to get backups off site to Azure

This user guide provides instructions on how to deploy and configure both a StoneFly Scale Out NAS Enterprise Cloud Drive virtual machine and Veeam Cloud Connect in the Microsoft Azure Cloud.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now