Solved

Reading Binary data from a socket connection

Posted on 2003-12-10
11
837 Views
Last Modified: 2008-02-01
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
Comment
Question by:andrewharris
11 Comments
 
LVL 18

Assisted Solution

by:testn
testn earned 250 total points
ID: 9911691
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
 
LVL 4

Expert Comment

by:krznpsk
ID: 9913181
You need to close the socketwriter in the server app, as well as flush it.
0
 
LVL 4

Author Comment

by:andrewharris
ID: 9915506
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
 
LVL 4

Author Comment

by:andrewharris
ID: 9915741
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
 
LVL 96

Expert Comment

by:Bob Learned
ID: 9916154
With the BinaryWriter, you can specify how many bytes to write to the file:

writer.Write(obj_SocketState.Buffer, 0, BytesRead)
0
3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

 
LVL 4

Author Comment

by:andrewharris
ID: 9916739
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
 
LVL 96

Accepted Solution

by:
Bob Learned earned 250 total points
ID: 9919919
When you receive 32600 bytes, what is the value of BytesRead?
0
 
LVL 4

Author Comment

by:andrewharris
ID: 9926343
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
 
LVL 96

Expert Comment

by:Bob Learned
ID: 9927890
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
 
LVL 4

Author Comment

by:andrewharris
ID: 9936695
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
 
LVL 4

Author Comment

by:andrewharris
ID: 9940265
OK Ignore my last stuff. really just irrelevant tothis question.

Split and away we go.

Thanks again.

Andrew
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Recently while returning home from work my wife (another .NET developer) was murmuring something. On further poking she said that she has been assigned a task where she has to serialize and deserialize objects and she is afraid of serialization. Wha…
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
Along with being a a promotional video for my three-day Annielytics Dashboard Seminor, this Micro Tutorial is an intro to Google Analytics API data.
Both in life and business – not all partnerships are created equal. As the demand for cloud services increases, so do the number of self-proclaimed cloud partners. Asking the right questions up front in the partnership, will enable both parties …

863 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now