Solved

Reading Binary data from a socket connection

Posted on 2003-12-10
11
841 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
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
Business Impact of IT Communications

What are the business impacts of how well businesses communicate during an IT incident? Targeting, speed, and transparency all matter. Find out more in this infographic.

 
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
 
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

How Do You Stack Up Against Your Peers?

With today’s modern enterprise so dependent on digital infrastructures, the impact of major incidents has increased dramatically. Grab the report now to gain insight into how your organization ranks against your peers and learn best-in-class strategies to resolve incidents.

Question has a verified solution.

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

For those of you who don't follow the news, or just happen to live under rocks, Microsoft Research released a beta SDK (http://www.microsoft.com/en-us/download/details.aspx?id=27876) for the Xbox 360 Kinect. If you don't know what a Kinect is (http:…
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…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

738 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