Return to Snippet

Revision: 12663
at March 24, 2009 10:51 by mcgraf


Initial Code
'server side
      Public Class Form1
   
          Private listener As System.Net.Sockets.TcpListener
   
          Private listenThread As System.Threading.Thread
   
       
   
          Private clients As New List(Of ConnectedClient) 'This list will store all connected clients.
   
       
   
          Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
   
              listener = New System.Net.Sockets.TcpListener(System.Net.IPAddress.Any, 43001) 'The TcpListener will listen for incoming connections at port 43001
   
              listener.Start() 'Start listening.
  
              listenThread = New System.Threading.Thread(AddressOf doListen) 'This thread will run the doListen method
  
              listenThread.IsBackground = True 'Since we dont want this thread to keep on running after the application closes, we set isBackground to true.
  
              listenThread.Start() 'Start executing doListen on the worker thread.
  
          End Sub
  
       
  
          Private Sub doListen()
  
              Dim incomingClient As System.Net.Sockets.TcpClient
  
              Do
  
                  incomingClient = listener.AcceptTcpClient 'Accept the incoming connection. This is a blocking method so execution will halt here until someone tries to connect.
  
                  Dim connClient As New ConnectedClient(incomingClient, Me) 'Create a new instance of ConnectedClient (check its constructor to see whats happening now).
  
                  AddHandler connClient.dataReceived, AddressOf Me.messageReceived
  
                  clients.Add(connClient) 'Adds the connected client to the list of connected clients.
  
       
  
              Loop
  
          End Sub
  
       
  
          Public Sub removeClient(ByVal client As ConnectedClient)
  
              If clients.Contains(client) Then
  
                  clients.Remove(client)
  
              End If
  
          End Sub
  
       
  
          Private Sub messageReceived(ByVal sender As ConnectedClient, ByVal message As String)
  
              'A message has been received from one of the clients.
  
              'To determine who its from, use the sender object.
  
              'sender.SendMessage can be used to reply to the sender.
  
       
  
              Dim data() As String = message.Split("|"c) 'Split the message on each | and place in the string array.
  
              Select Case data(0)
  
                  Case "CONNECT"
  
                      'We use GetClientByName to make sure no one else is using this username.
  
                      'It will return Nothing if the username is free.
  
                      'Since the client sent the message in this format: CONNECT|UserName, the username will be in the array on index 1.
  
                      If GetClientByName(data(1)) Is Nothing Then
  
                          'The username is not taken, we can safely assign it to the sender.
  
                          sender.Username = data(1)
  
                      End If
  
                  Case "DISCONNECT"
  
                      removeClient(sender)
  
              End Select
  
       
  
          End Sub
  
       
  
          Private Function GetClientByName(ByVal name As String) As ConnectedClient
  
              For Each cc As ConnectedClient In clients
  
                  If cc.Username = name Then
  
                      Return cc 'client found, return it.
  
                  End If
  
              Next
  
              'If we've reached this part of the method, there is no client by that name
  
              Return Nothing
  
        End Function
  
      End Class 

'client side
   
      Public Class ConnectedClient
   
          Private mClient As System.Net.Sockets.TcpClient
   
       
   
          Private mUsername As String
   
          Private mParentForm As Form1
   
          Private readThread As System.Threading.Thread
   
          Private Const MESSAGE_DELIMITER As Char = ControlChars.Cr
   
       
   
          Public Event dataReceived(ByVal sender As ConnectedClient, ByVal message As String)
  
       
  
          Sub New(ByVal client As System.Net.Sockets.TcpClient, ByVal parentForm As Form1)
  
              mParentForm = parentForm
  
              mClient = client
  
       
  
              readThread = New System.Threading.Thread(AddressOf doRead)
  
              readThread.IsBackground = True
  
              readThread.Start()
  
          End Sub
  
       
  
          Public Property Username() As String
  
              Get
  
                  Return mUsername
  
              End Get
  
              Set(ByVal value As String)
  
                  mUsername = value
  
              End Set
  
          End Property
  
       
  
          Private Sub doRead()
  
              Const BYTES_TO_READ As Integer = 255
  
              Dim readBuffer(BYTES_TO_READ) As Byte
  
              Dim bytesRead As Integer
  
              Dim sBuilder As New System.Text.StringBuilder
  
              Do
  
                  bytesRead = mClient.GetStream.Read(readBuffer, 0, BYTES_TO_READ)
  
                  If (bytesRead > 0) Then
  
                      Dim message As String = System.Text.Encoding.UTF8.GetString(readBuffer, 0, bytesRead)
  
                      If (message.IndexOf(MESSAGE_DELIMITER) > -1) Then
  
       
  
                          Dim subMessages() As String = message.Split(MESSAGE_DELIMITER)
  
       
  
                          'The first element in the subMessages string array must be the last part of the current message.
  
                          'So we append it to the StringBuilder and raise the dataReceived event
  
                          sBuilder.Append(subMessages(0))
  
                          RaiseEvent dataReceived(Me, sBuilder.ToString)
  
                          sBuilder = New System.Text.StringBuilder
  
       
  
                          'If there are only 2 elements in the array, we know that the second one is an incomplete message,
  
                          'though if there are more then two then every element inbetween the first and the last are complete messages:
  
                          If subMessages.Length = 2 Then
  
                              sBuilder.Append(subMessages(1))
  
                          Else
  
                              For i As Integer = 1 To subMessages.GetUpperBound(0) - 1
  
                                  RaiseEvent dataReceived(Me, subMessages(i))
  
                              Next
  
                              sBuilder.Append(subMessages(subMessages.GetUpperBound(0)))
  
                          End If
  
                      Else
  
       
  
                          'MESSAGE_DELIMITER was not found in the message, so we just append everything to the stringbuilder.
  
                          sBuilder.Append(message)
  
                      End If
  
                  End If
  
              Loop
  
          End Sub
  
       
  
          Public Sub SendMessage(ByVal msg As String)
  
              Dim sw As IO.StreamWriter
  
              Try
  
                  SyncLock mClient.GetStream
  
                      sw = New IO.StreamWriter(mClient.GetStream) 'Create a new streamwriter that will be writing directly to the networkstream.
  
                      sw.Write(msg)
  
                      sw.Flush()
  
                  End SyncLock
  
              Catch ex As Exception
  
                  MessageBox.Show(ex.ToString)
  
              End Try
  
              'As opposed to writing to a file, we DONT call close on the streamwriter, since we dont want to close the stream.
  
          End Sub
  
       
  
      End Class 

'client side form

   
      Public Class Form1
   
          Private client As System.Net.Sockets.TcpClient
   
       
   
          Private Const BYTES_TO_READ As Integer = 255
   
          Private readBuffer(BYTES_TO_READ) As Byte
   
       
          Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
   
              client = New System.Net.Sockets.TcpClient("localhost", 43001)
   
              client.GetStream.BeginRead(readBuffer, 0, BYTES_TO_READ, AddressOf doRead, Nothing)
  
          End Sub
  
       
  
          Private Sub doRead(ByVal ar As System.IAsyncResult)
  
              Dim totalRead As Integer
  
              Try
  
                  totalRead = client.GetStream.EndRead(ar) 'Ends the reading and returns the number of bytes read.
  
              Catch ex As Exception
  
                  'The underlying socket have probably been closed OR an error has occured whilst trying to access it, either way, this is where you should remove close all eventuall connections
  
                  'to this client and remove it from the list of connected clients.
  
              End Try
  
       
  
                  If totalRead > 0 Then
  
                      'the readBuffer array will contain everything read from the client.
  
                      Dim receivedString As String = System.Text.Encoding.UTF8.GetString(readBuffer, 0, totalRead)
  
                      messageReceived(receivedString)
  
                  End If
  
       
  
                  Try
  
                      client.GetStream.BeginRead(readBuffer, 0, BYTES_TO_READ, AddressOf doRead, Nothing) 'Begin the reading again.
  
                  Catch ex As Exception
  
                      'The underlying socket have probably been closed OR an error has occured whilst trying to access it, either way, this is where you should remove close all eventuall connections
  
                      'to this client and remove it from the list of connected clients.
  
                  End Try
  
          End Sub
  
       
  
          Private Sub messageReceived(ByVal message As String)
  
              MessageBox.Show(message)
  
          End Sub
  
       
  
       
  
       
  
          Private Sub SendMessage(ByVal msg As String)
  
              Dim sw As IO.StreamWriter
  
              Try
  
                  sw = New IO.StreamWriter(client.GetStream)
  
                  sw.Write(msg)
  
                  sw.Flush()
  
              Catch ex As Exception
  
                  MessageBox.Show(ex.ToString)
  
              End Try
  
          End Sub
  
      End Class 

Initial URL


Initial Description


Initial Title
TCP socket server example 2

Initial Tags


Initial Language
VB.NET