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