File transfer

pitaridis

Well-known member
Joined
Nov 18, 2005
Messages
63
Programming Experience
10+
About 10 days I try to make a client/server application in order to transfer a test file from one pc to another. The bad thing about this is that it needs 2 programming skills that I have never used until now. It needs threads management and network programming. Combining a lot of examples that I have found through Google I made the following code.

Server
VB.NET:
Public Class frmServer
    Private myThread As System.Threading.Thread
    Private myListener As System.Net.Sockets.TcpListener
    Private myClients As New Hashtable()

    Dim friends As String

    Dim i As Integer = 0
    Dim myport As Integer = 1234

    'displays the received text 
    Private Sub UpdateStatus(ByVal t As String)
        chatbox.Items.Add(t)
        chatbox.SetSelected(chatbox.Items.Count - 1, True)
    End Sub

    'gets the listening port
    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Try
            myThread = New System.Threading.Thread(AddressOf DoListen)
            myThread.Start()

            UpdateStatus("Server Active on port:" & myport)
        Catch ex As Exception
            MsgBox("error")
            End
        End Try
    End Sub

    ' starts listening for clients
    Private Sub DoListen()
        Try
            Dim IPAddress() As Byte = {127, 0, 0, 1}
            myListener = New System.Net.Sockets.TcpListener(New Net.IPAddress(IPAddress), myport)
            myListener.Start()
            Do
                Dim x As New Client(myListener.AcceptTcpClient)
                AddHandler x.Connected, AddressOf OnConnected
                AddHandler x.Disconnected, AddressOf OnDisconnected
                AddHandler x.LineReceived, AddressOf OnLineReceived
                myClients.Add(x.ID, x) 'adds cleints to a hash table
            Loop Until False
        Catch
        End Try
    End Sub

    Private Sub OnConnected(ByVal sender As Client)
        UpdateStatus("Connected client " & sender.ID)
    End Sub

    ' removes a disconnected client from the list
    Private Sub OnDisconnected(ByVal sender As Client)
        UpdateStatus("Disconnected client " & sender.ID)
        myClients.Remove(sender.ID)
        friendsbox.Items.Remove(friends)
    End Sub

    Private NumberOfFiles As Integer = 5

    Private Sub OnLineReceived(ByVal sender As Client, ByVal Data As String)
        If Data.Substring(0, 15) = "CloseConnection" Then
            sender.Disconnect()
        ElseIf Data.Substring(0, 16) = "AskNumberOfFiles" Then
            sender.Send("AskNumberOfFiles:" & NumberOfFiles)
        Else
            sender.Send("Data")
        End If
    End Sub

    Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
        On Error Resume Next
        myListener.Stop()
    End Sub

    Private Sub LinkLabel2_LinkClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles LinkLabel2.LinkClicked
        On Error Resume Next
        myListener.Stop()
        End
    End Sub

    Private Sub SendToAllClients(ByVal Data As String)
        Dim qn As Client
        Dim qd As DictionaryEntry
        'sends the received strings and name list to all clients
        For Each qd In myClients
            qn = qd.Value
            qn.Send(Data & vbCrLf)
            For i As Integer = 0 To friendsbox.Items.Count - 1
                qn.Send("client:" & friendsbox.Items.Item(i))
            Next
        Next
    End Sub
End Class

'the main client class
Public Class Client
    Public Event Connected(ByVal sender As Client)
    Public Event Disconnected(ByVal sender As Client)
    Public Event LineReceived(ByVal sender As Client, ByVal Data As String)

    Private MyBuffer(1024) As Byte
    Private TextArrived As New System.Text.StringBuilder()

    ' only one of the following is used at any time
    Private ClientConnection As System.Net.Sockets.TcpClient

    ' initialize with a TcpClient object
    Public Sub New(ByVal client As System.Net.Sockets.TcpClient)
        ClientConnection = client
        RaiseEvent Connected(Me)
        ClientConnection.GetStream.BeginRead(MyBuffer, 0, 1024, AddressOf DoStreamReceive, Nothing)
    End Sub

    ' Connection ID 
    Private m_ConnectionID As Guid = Guid.NewGuid
    Public ReadOnly Property ID() As String
        Get
            Return m_ConnectionID.ToString
        End Get
    End Property

    Public Sub Disconnect()
        ClientConnection.Close()
        RaiseEvent Disconnected(Me)
    End Sub

    'gets the received bytes
    Private Sub DoStreamReceive(ByVal ar As IAsyncResult)
        Dim intCount As Integer

        Try
            SyncLock ClientConnection.GetStream
                intCount = ClientConnection.GetStream.EndRead(ar)
            End SyncLock
            If intCount < 1 Then
                RaiseEvent Disconnected(Me)
                Exit Sub
            End If

            BuildString(MyBuffer, 0, intCount)
            SyncLock ClientConnection.GetStream
                ClientConnection.GetStream.BeginRead(MyBuffer, 0, 1024, AddressOf DoStreamReceive, Nothing)
            End SyncLock
        Catch e As Exception
            RaiseEvent Disconnected(Me)
        End Try
    End Sub

    Private Sub BuildString(ByVal Bytes() As Byte, ByVal offset As Integer, ByVal count As Integer)
        Dim intIndex As Integer

        For intIndex = offset To offset + count - 1
            If Bytes(intIndex) = 13 Then
                RaiseEvent LineReceived(Me, TextArrived.ToString)
                TextArrived = New System.Text.StringBuilder()
            Else
                TextArrived.Append(ChrW(Bytes(intIndex)))
            End If
        Next
    End Sub

    'sends to the clients
    Public Sub Send(ByVal Data As String)
        SyncLock ClientConnection.GetStream
            Dim w As New IO.StreamWriter(ClientConnection.GetStream)
            w.Write(Data & vbCrLf)
            w.Flush()
        End SyncLock
    End Sub
End Class

Client
VB.NET:
Public Class frmClient
    Public Delegate Sub DisplayInvoker(ByVal t As String)
    Dim myport As Integer = 1234
    Dim Address As String = "localhost"

    Dim a As String
    Dim b As String
    Dim hrs, secs, mins As Integer
    Dim f As Integer

    Private myclient As System.Net.Sockets.TcpClient
    Private mydata(1024) As Byte
    Private mytext As New System.Text.StringBuilder()

    'procedure to send strings to the server
    Private Sub Send(ByVal t As String)
        On Error Resume Next
        Dim w As New IO.StreamWriter(myclient.GetStream)
        w.Write(t & vbCr)
        w.Flush()
    End Sub

    'reads bytes from the server
    Private Sub DoRead(ByVal ar As IAsyncResult)
        Dim intCount As Integer

        Try
            intCount = myclient.GetStream.EndRead(ar)
            If intCount < 1 Then
                chatbox.AppendText("Disconnected" & vbCrLf)
                Exit Sub
            End If

            BuildString(mydata, 0, intCount)

            myclient.GetStream.BeginRead(mydata, 0, 1024, AddressOf DoRead, Nothing)
        Catch e As Exception
            '  chatbox.AppendText("Disconnected" & vbCrLf)
        End Try
    End Sub

    'transforms bytes into strings
    Private Sub BuildString(ByVal Bytes() As Byte, ByVal offset As Integer, ByVal count As Integer)
        Dim intIndex As Integer

        For intIndex = offset To offset + count - 1
            If Bytes(intIndex) = 10 Then
                mytext.Append(vbLf)

                Dim params() As Object = {mytext.ToString}
                Me.Invoke(New DisplayInvoker(AddressOf Me.DisplayText), params)

                mytext = New System.Text.StringBuilder()
            Else
                mytext.Append(ChrW(Bytes(intIndex)))
            End If
        Next
    End Sub

    'displays the received text to the chat box
    Private Sub DisplayText(ByVal Data As String)
        If Data.Substring(0, 17) = "AskNumberOfFiles:" Then
            Dim value As Integer = Val(Data.Substring(17, Data.Length - 17))
            chatbox.AppendText(value)
        End If
    End Sub

    'when pressed client requests connection
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        chatbox.AppendText("Requesting Connection..." & vbCrLf)
        myclient = New System.Net.Sockets.TcpClient(Address, myport)
        myclient.GetStream.BeginRead(mydata, 0, 1024, AddressOf DoRead, Nothing)
        chatbox.AppendText("Connected..." & vbCrLf)
        chatbox.AppendText("Connected to " & Address & ":" & myport & vbCrLf)
        Button1.Visible = False
        Button4.Visible = True
    End Sub

    Private Sub Form1_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Closed
        Send("CloseConnection")
    End Sub

    'disconnects from the server
    Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
        Send("CloseConnection")
        chatbox.AppendText("Disconnected" & vbCrLf)
        Button4.Visible = False
        Button1.Visible = True
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Send("AskNumberOfFiles")
    End Sub
End Class

What I have done until now is that I have the ability to setup a basic communication between the two computers. I also want to be able to transfer a file (test). The communication that I want to have is the following.

Client -> Asks the number of files (tests) that are available at the moment.
Server -> Gives a number
Client -> Asks the names of the files (tests) so that the user will be able to select a test
Server -> Gives the tests
Client -> Asks for a test
Server -> Send the file for the selected test
Client -> Saves locally the file so that the application will be able to start the test.

If someone can correct logical errors in my example or give a better solution it will be very helpful. I have to finish this application as soon as possible.

Thanks you in advance for your help.
 
Back
Top