Click here to Skip to main content
15,878,959 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I have been building a VB.NET application which works by sharing out data between a TCP client and TCP server. The data being shared are small XML, CSV and PNG files. I have limited knowledge on TCP projects and thought it be a feasible idea to encode these files to Base64, send them as strings and then once at their destinations, un-encode the data from Base64 to the desired file information. This idea just doesn't seem to work and I can't find a solution. Also, I find it a bit hard to understand because in previous projects, I have sent Base64 encoded strings via TCP regarding data which I wanted to remain confidential such as passwords or email addresses of staff members which works fine. The first thing that I discovered upon Googling is that the files which though small exceed 50KB would mean that they are better sent of as packets fine. I have seen a few easy to follow projects that send files via TCP using packets... However, the projects all seem to be examples of Clients sending to Servers and not visa-versa or as what I want both ways. Determined not to give up I came up with the following code but then ran into problems with it which leads me to believe that bytes sent as packets can only be done in a Server to Client situation?

Server Code:

VB.NET
Imports System.Net
Imports System.Net.Sockets
Imports System.Text

Public Class Form1

    Dim SERVER As TcpListener
    Dim LIST_OF_CLIENTS As New List(Of TcpClient)

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Try
            '(Sets up connection parameters)
            Dim IP As String = "10.32.48.92"
            Dim PORT As Integer = 5432

            '(Creates an active listner)
            SERVER = New TcpListener(IPAddress.Parse(IP), PORT)
            SERVER.Start()

            '(New thread to keep reciving messages from clients)
            Threading.ThreadPool.QueueUserWorkItem(AddressOf NEW_CLIENT)

        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub

    Private Sub NEW_CLIENT()
        Dim CLIENT As TcpClient = SERVER.AcceptTcpClient
        Try

            '(Adds potential new clients)
            LIST_OF_CLIENTS.Add(CLIENT)

            '(New thread to keep reciving messages from potential new clients)
            Threading.ThreadPool.QueueUserWorkItem(AddressOf NEW_CLIENT)

            While True '(his while puts it on a loop to keep getting messages from client)

                '(The following gets all incomming messages)
                Dim NETWORK_STREAM As NetworkStream = CLIENT.GetStream

                Dim BUFFER_TO_RECIVE(100000) As Byte

                NETWORK_STREAM.Read(BUFFER_TO_RECIVE, 0, BUFFER_TO_RECIVE.Length)
                Dim TEXT As String = Encoding.UTF8.GetString(BUFFER_TO_RECIVE)

                '(The following forward the message to all clients 
                ' except the client that sent the message)
                For Each c As TcpClient In LIST_OF_CLIENTS
                    If c IsNot CLIENT Then
                        Dim NEW_NETWORK_STREAM As NetworkStream = c.GetStream()

                        NEW_NETWORK_STREAM.Write(Encoding.UTF8.GetBytes(TEXT), 0, TEXT.Length)

                    End If
                Next

            End While

        Catch ex As Exception

            '(If connection with client failed,
            ' we want to remove tht client from list)
            If LIST_OF_CLIENTS.Contains(CLIENT) Then
                LIST_OF_CLIENTS.Remove(CLIENT)
            End If
            ' MsgBox(ex.Message) ' (by commenting this the error 
            ' that a client has bombed out dose not apear on screen)
        End Try
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    End Sub
End Class


Client Code:

VB.NET
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.IO

Public Class Form1

    Const BUFFER_SIZE As Integer = 1024 * 20

    Dim IP As String = "10.32.48.92"
    Dim PORT As Integer = 5432
    Dim CLIENT As New TcpClient(IP, PORT)

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        '(This connects to server)
        Try

            CheckForIllegalCrossThreadCalls = False '(this halts crossthreading errors cased by the way threads work, which is apparently a big pain)

            '(Create a new thread to listen if connection is successful... for the receiving of any new messages)
            Threading.ThreadPool.QueueUserWorkItem(AddressOf RECIVE_MESAGES)

            Me.AcceptButton = Button2 '(This causes the enter key to trigger the button2.click event)

        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        Try

            'sends filename, filelength, filebytes
            Dim fullfilename As String = "C:\ToSomeFile.png"
            Dim info As New FileInfo(fullfilename)

            CLIENT.Connect(Net.IPAddress.Parse(IP), PORT) 'send the file to client IP address

            'writes a String and a Long with binarywriter (wrapping networkstream)
            Dim bw As New BinaryWriter(CLIENT.GetStream)
            bw.Write(info.Name)
            bw.Write(info.Length)

            'using filestream to read file, 
            'writes this directly to networkstream
            Using fs As New FileStream(fullfilename, FileMode.Open, FileAccess.Read)
                Dim buffer(BUFFER_SIZE) As Byte
                Dim reads As Integer = -1

                Dim totalRead As Integer = 0
                Do Until reads = 0
                    reads = fs.Read(buffer, 0, buffer.Length)
                    CLIENT.GetStream.Write(buffer, 0, reads)
                    totalRead += reads
                Loop
            End Using

            bw.Close()
            CLIENT.Close()

        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub

    Private Sub RECIVE_MESAGES(ByVal ar As IAsyncResult)
        Try
            While True

                Dim buffer(BUFFER_SIZE) As Byte
                Dim readstotal As Long = 0

                'using binaryreader (wrapped networkstream) to read a String and a Long
                Dim br As New BinaryReader(CLIENT.GetStream)
                Dim filename, filepath As String, filelen As Long
                filename = br.ReadString
                filelen = br.ReadInt64

                If filename.ToUpper.Contains("PNG") Then
                    Dim di As New DirectoryInfo(Application.StartupPath & "\PNG")
                    If Not di.Exists Then
                        Directory.CreateDirectory(Application.StartupPath & "\PNG")
                    End If
                    filepath = Path.Combine(Application.StartupPath & "\PNG\", filename)
                ElseIf filename.ToUpper.Contains("XML") Then
                    Dim di As New DirectoryInfo(Application.StartupPath & "XML")
                    If Not di.Exists Then
                        Directory.CreateDirectory(Application.StartupPath & "\XML")
                    End If
                    filepath = Path.Combine(Application.StartupPath & "\XML\", filename)
                End If


                Dim reads As Integer = -1
                'using filestream to write read filebytes directly from networkstream
                Using fs As New FileStream(filepath, FileMode.Create, FileAccess.Write)
                    Do Until readstotal = filelen
                        reads = CLIENT.GetStream.Read(buffer, 0, buffer.Length)
                        fs.Write(buffer, 0, reads)
                        readstotal += reads
                    Loop
                End Using

            End While
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub

End Class


I, as second attempt, then returned to my initial idea and encoded the files to Base64 though this time before sending it via TCP, I read the data out to a text-box copying the text-box results and checking on-line with diverse Base64 to Image sites if the Base64 code from the text-box delivered the same image which it did. I then proceeded with sending the data via TCP but am now met with a situation that says the Base64 is incorrect. The error says “The input is not a valid base-64 string as it contains a non-base 64 character...” which after some more Googling has led me to believe the encoding of the string sent by the TCP corrupted the Base64 format apparently changing it to encoding.UTF8 would fix it, however to no avail.

The following code shows this attempt:

Server Code:

VB.NET
Imports System.Net
Imports System.Net.Sockets
Imports System.Text

Public Class Form1

    Dim SERVER As TcpListener
    Dim LIST_OF_CLIENTS As New List(Of TcpClient)

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Try
            '(Sets up connection parameters)
            Dim IP As String = "10.43.71.241"
            Dim PORT As Integer = 5432

            '(Creates an active listner)
            SERVER = New TcpListener(IPAddress.Parse(IP), PORT)
            SERVER.Start()

            '(New thread to keep reciving messages from clients)
            Threading.ThreadPool.QueueUserWorkItem(AddressOf NEW_CLIENT)

        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub

    Private Sub NEW_CLIENT()
        Dim CLIENT As TcpClient = SERVER.AcceptTcpClient
        Try

            '(Adds potential new clients)
            LIST_OF_CLIENTS.Add(CLIENT)

            '(New thread to keep reciving messages from potential new clients)
            Threading.ThreadPool.QueueUserWorkItem(AddressOf NEW_CLIENT)

            While True '(his while puts it on a loop to keep getting messages from client)

                '(The following gets all incomming messages)
                Dim NETWORK_STREAM As NetworkStream = CLIENT.GetStream

                Dim BUFFER_TO_RECIVE(1000000) As Byte

                NETWORK_STREAM.Read(BUFFER_TO_RECIVE, 0, BUFFER_TO_RECIVE.Length)
                Dim TEXT As String = Encoding.UTF8.GetString(BUFFER_TO_RECIVE)

                '(The following forward the message to all clients except the client that sent the message)
                For Each c As TcpClient In LIST_OF_CLIENTS
                    If c IsNot CLIENT Then
                        Dim NEW_NETWORK_STREAM As NetworkStream = c.GetStream()

                        NEW_NETWORK_STREAM.Write(Encoding.UTF8.GetBytes(TEXT), 0, TEXT.Length)

                    End If
                Next

            End While

        Catch ex As Exception

            '(If connection with client failed we want to remove tht client from list)
            If LIST_OF_CLIENTS.Contains(CLIENT) Then
                LIST_OF_CLIENTS.Remove(CLIENT)
            End If
            ' MsgBox(ex.Message) ' (by commenting this the error that a client has bombed out dose not apear on screen)
        End Try
    End Sub 


Client Code:

VB.NET
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.IO

Public Class Form1

    Dim CLIENT As TcpClient

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        '(This connects to server)
        Try
            Dim IP As String = "10.43.71.241"
            Dim PORT As Integer = 5432

            CLIENT = New TcpClient(IP, PORT)

            CheckForIllegalCrossThreadCalls = False '(this halts crossthreading errors cased by the way threads work, whic is apparently a big pain in the arse)

            '(Create a new thread to listen if connection is successfull... for the reciving of any new messages)
            Threading.ThreadPool.QueueUserWorkItem(AddressOf RECIVE_MESAGES)

            Me.AcceptButton = Button2 '(This casses the enter key to triggre the button2.click event)

        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click

        Dim image As Image = image.FromFile("C:\TOM\jane.png")
        Dim format As System.Drawing.Imaging.ImageFormat = System.Drawing.Imaging.ImageFormat.Png

        Using ms As New MemoryStream()
            ' Convert Image to byte[]  
            image.Save(ms, format)
            Dim imageBytes As Byte() = ms.ToArray()

            ' Convert byte[] to Base64 String  
            Dim base64String As String = Convert.ToBase64String(imageBytes)

            Try
                Dim NETWORK_STREAM As NetworkStream = CLIENT.GetStream '(Creates the nesesary stream)

                NETWORK_STREAM.Write(Encoding.UTF8.GetBytes(base64String), 0, base64String.Length) '(Writes the the stream just created in the above step)
            Catch ex As Exception
                MsgBox(ex.Message)
            End Try

        End Using
    End Sub

    Private Sub RECIVE_MESAGES()
        Try
            While True
                Dim NETWORK_STREAM As NetworkStream = CLIENT.GetStream

                Dim BUFFER_TO_RECIVE(100000) As Byte
                NETWORK_STREAM.Read(BUFFER_TO_RECIVE, 0, BUFFER_TO_RECIVE.Length)

                Dim TEXT As String = Encoding.UTF8.GetString(BUFFER_TO_RECIVE)

                '+++

                Dim base64String As String = TEXT
                ' Convert Base64 String to byte[]  
                Dim imageBytes As Byte() = Convert.FromBase64String(base64String)
                Dim ms As New MemoryStream(imageBytes, 0, imageBytes.Length)

                ' Convert byte[] to Image  
                ms.Write(imageBytes, 0, imageBytes.Length)
                Dim image__1 As Image = Image.FromStream(ms, True)

                PictureBox1.Image = image__1

                Dim bm As New Bitmap(PictureBox1.Image)
                bm.Save("c:\users\user\desktop\test.png", System.Drawing.Imaging.ImageFormat.Png)

                '(the following displays the text in ritch textbox)
                    TextBox3.Text = TEXT

            End While
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub 


I seriously have made an effort to try and figure this one out, but just can't find the answer. Can anyone help me?

What I have tried:

See above section for examples I have tried
Posted
Updated 10-Aug-23 9:40am
v2
Comments
Richard MacCutchan 19-Jul-19 3:30am    
A client can send anything to a server, and a server can send anything to a client. TCP is merely a protocol for transmitting data between two end points, it does not care what that data contains, nor does it care (or know) which is the client and which is the server. The key to your problem is to create a message exchange protocol between your client and the server, so they can decide whether they should be in sending or receiving mode at any point in time.

1 solution

"This idea doesn't seem to work" doesn't tell us ANYTHING. Beyond that, TCP is merely a transoport mechanism and already uses "packets, so there's that...

Are you doing sopmething like this to encode images?

C#
byte[] imageArray = System.IO.File.ReadAllBytes(@"path/imagefile.ext");
string base64ImageRepresentation = Convert.ToBase64String(imageArray);


And this to decode images?

C#
var img = Image.FromStream(new MemoryStream(Convert.FromBase64String(base64String)));


I know, you're asking about VB, but this code is easily convertible...
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900