Solved

Reading Binary data from a socket connection

Posted on 2003-12-10
11
840 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
Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

 
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

Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

The object model of .Net can be overwhelming at times – so overwhelming that quite trivial tasks often take hours of research. In this case, the task at hand was to populate the datagrid from SQL Server database in Visual Studio 2008 Windows applica…
In my previous two articles we discussed Binary Serialization (http://www.experts-exchange.com/A_4362.html) and XML Serialization (http://www.experts-exchange.com/A_4425.html). In this article we will try to know more about SOAP (Simple Object Acces…
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…
Email security requires an ever evolving service that stays up to date with counter-evolving threats. The Email Laundry perform Research and Development to ensure their email security service evolves faster than cyber criminals. We apply our Threat…

830 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