[/COLOR]
[COLOR=white][SIZE=2]Public[/SIZE][SIZE=2]Class[/SIZE][SIZE=2] Form1[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Private[/SIZE][SIZE=2] listener [/SIZE][SIZE=2]As[/SIZE][SIZE=2] System.Net.Sockets.TcpListener[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Private[/SIZE][SIZE=2] listenThread [/SIZE][SIZE=2]As[/SIZE][SIZE=2] System.Threading.Thread[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Private[/SIZE][SIZE=2] clients [/SIZE][SIZE=2]As[/SIZE][SIZE=2]New[/SIZE][SIZE=2] List([/SIZE][SIZE=2]Of[/SIZE][SIZE=2] ConnectedClient) [/SIZE][SIZE=2]'This list will store all connected clients. [/SIZE][/COLOR]
[COLOR=white][SIZE=2]Private[/SIZE][SIZE=2]Sub[/SIZE][SIZE=2] Form1_Load([/SIZE][SIZE=2]ByVal[/SIZE][SIZE=2] sender [/SIZE][SIZE=2]As[/SIZE][SIZE=2] System.Object, [/SIZE][SIZE=2]ByVal[/SIZE][SIZE=2] e [/SIZE][SIZE=2]As[/SIZE][SIZE=2] System.EventArgs) [/SIZE][SIZE=2]Handles[/SIZE][SIZE=2]MyBase[/SIZE][SIZE=2].Load[/SIZE][/COLOR]
[COLOR=white][SIZE=2]listener = [/SIZE][SIZE=2]New[/SIZE][SIZE=2] System.Net.Sockets.TcpListener(System.Net.IPAddress.Any, 43001) [/SIZE][SIZE=2]'The TcpListener will listen for incoming connections at port 43001 [/SIZE][/COLOR]
[COLOR=white][SIZE=2]listener.Start() [/SIZE][SIZE=2]'Start listening. [/SIZE][/COLOR]
[COLOR=white][SIZE=2]listenThread = [/SIZE][SIZE=2]New[/SIZE][SIZE=2] System.Threading.Thread([/SIZE][SIZE=2]AddressOf[/SIZE][SIZE=2] doListen) [/SIZE][SIZE=2]'This thread will run the doListen method [/SIZE][/COLOR]
[COLOR=white][SIZE=2]listenThread.IsBackground = [/SIZE][SIZE=2]True[/SIZE][SIZE=2]'Since we dont want this thread to keep on running after the application closes, we set isBackground to true. [/SIZE][/COLOR]
[COLOR=white][SIZE=2]listenThread.Start() [/SIZE][SIZE=2]'Start executing doListen on the worker thread. [/SIZE][/COLOR]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]Sub[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Private[/SIZE][SIZE=2]Sub[/SIZE][SIZE=2] doListen()[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Dim[/SIZE][SIZE=2] incomingClient [/SIZE][SIZE=2]As[/SIZE][SIZE=2] System.Net.Sockets.TcpClient[/SIZE][/COLOR]
[SIZE=2][COLOR=white]Do[/COLOR][/SIZE]
[COLOR=white][SIZE=2]incomingClient = listener.AcceptTcpClient [/SIZE][SIZE=2]'Accept the incoming connection. This is a blocking method so execution will halt here until someone tries to connect. [/SIZE][/COLOR]
[COLOR=white][SIZE=2]Dim[/SIZE][SIZE=2] connClient [/SIZE][SIZE=2]As[/SIZE][SIZE=2]New[/SIZE][SIZE=2] ConnectedClient(incomingClient, [/SIZE][SIZE=2]Me[/SIZE][SIZE=2]) [/SIZE][SIZE=2]'Create a new instance of ConnectedClient (check its constructor to see whats happening now). [/SIZE][/COLOR]
[COLOR=white][SIZE=2]AddHandler[/SIZE][SIZE=2] connClient.dataReceived, [/SIZE][SIZE=2]AddressOf[/SIZE][SIZE=2]Me[/SIZE][SIZE=2].messageReceived[/SIZE][/COLOR]
[COLOR=white][SIZE=2]clients.Add(connClient) [/SIZE][SIZE=2]'Adds the connected client to the list of connected clients. [/SIZE][/COLOR]
[SIZE=2][COLOR=white]Loop[/COLOR][/SIZE]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]Sub[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Public[/SIZE][SIZE=2]Sub[/SIZE][SIZE=2] removeClient([/SIZE][SIZE=2]ByVal[/SIZE][SIZE=2] client [/SIZE][SIZE=2]As[/SIZE][SIZE=2] ConnectedClient)[/SIZE][/COLOR]
[COLOR=white][SIZE=2]If[/SIZE][SIZE=2] clients.Contains(client) [/SIZE][SIZE=2]Then[/SIZE][/COLOR]
[SIZE=2][COLOR=white]clients.Remove(client)[/COLOR][/SIZE]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]If[/SIZE][/COLOR]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]Sub[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Private[/SIZE][SIZE=2]Sub[/SIZE][SIZE=2] messageReceived([/SIZE][SIZE=2]ByVal[/SIZE][SIZE=2] sender [/SIZE][SIZE=2]As[/SIZE][SIZE=2] ConnectedClient, [/SIZE][SIZE=2]ByVal[/SIZE][SIZE=2] message [/SIZE][SIZE=2]As[/SIZE][SIZE=2]String[/SIZE][SIZE=2]) [/SIZE][SIZE=2]'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. [/SIZE][/COLOR]
[COLOR=white][SIZE=2]Dim[/SIZE][SIZE=2] data() [/SIZE][SIZE=2]As[/SIZE][SIZE=2]String[/SIZE][SIZE=2] = message.Split([/SIZE][SIZE=2]"|"c[/SIZE][SIZE=2]) [/SIZE][SIZE=2]'Split the message on each | and place in the string array. [/SIZE][/COLOR]
[COLOR=white][SIZE=2]Select[/SIZE][SIZE=2]Case[/SIZE][SIZE=2] data(0)[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Case[/SIZE][SIZE=2]"CONNECT"[/SIZE][SIZE=2]'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. [/SIZE][/COLOR]
[COLOR=white][SIZE=2]If[/SIZE][SIZE=2] GetClientByName(data(1)) [/SIZE][SIZE=2]Is[/SIZE][SIZE=2]Nothing[/SIZE][SIZE=2]Then[/SIZE][SIZE=2]'The username is not taken, we can safely assign it to the sender. [/SIZE][/COLOR]
[SIZE=2][COLOR=white]sender.Username = data(1)[/COLOR][/SIZE]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]If[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Case[/SIZE][SIZE=2]"DISCONNECT"[/SIZE][/COLOR]
[SIZE=2][COLOR=white]removeClient(sender)[/COLOR][/SIZE]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]Select[/SIZE][/COLOR]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]Sub[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Private[/SIZE][SIZE=2]Function[/SIZE][SIZE=2] GetClientByName([/SIZE][SIZE=2]ByVal[/SIZE][SIZE=2] name [/SIZE][SIZE=2]As[/SIZE][SIZE=2]String[/SIZE][SIZE=2]) [/SIZE][SIZE=2]As[/SIZE][SIZE=2] ConnectedClient[/SIZE][/COLOR]
[COLOR=white][SIZE=2]For[/SIZE][SIZE=2]Each[/SIZE][SIZE=2] cc [/SIZE][SIZE=2]As[/SIZE][SIZE=2] ConnectedClient [/SIZE][SIZE=2]In[/SIZE][SIZE=2] clients[/SIZE][/COLOR]
[COLOR=white][SIZE=2]If[/SIZE][SIZE=2] cc.Username = name [/SIZE][SIZE=2]Then[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Return[/SIZE][SIZE=2] cc [/SIZE][SIZE=2]'client found, return it. [/SIZE][/COLOR]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]If[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Next[/SIZE][SIZE=2]'If we've reached this part of the method, there is no client by that name [/SIZE][/COLOR]
[COLOR=white][SIZE=2]Return[/SIZE][SIZE=2]Nothing[/SIZE][/COLOR]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]Function[/SIZE][/COLOR]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]Class[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Public[/SIZE][SIZE=2]Class[/SIZE][SIZE=2] ConnectedClient[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Private[/SIZE][SIZE=2] mClient [/SIZE][SIZE=2]As[/SIZE][SIZE=2] System.Net.Sockets.TcpClient[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Private[/SIZE][SIZE=2] mUsername [/SIZE][SIZE=2]As[/SIZE][SIZE=2]String[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Private[/SIZE][SIZE=2] mParentForm [/SIZE][SIZE=2]As[/SIZE][SIZE=2] Form1[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Private[/SIZE][SIZE=2] readThread [/SIZE][SIZE=2]As[/SIZE][SIZE=2] System.Threading.Thread[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Private[/SIZE][SIZE=2]Const[/SIZE][SIZE=2] MESSAGE_DELIMITER [/SIZE][SIZE=2]As[/SIZE][SIZE=2]Char[/SIZE][SIZE=2] = ControlChars.Cr[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Public[/SIZE][SIZE=2]Event[/SIZE][SIZE=2] dataReceived([/SIZE][SIZE=2]ByVal[/SIZE][SIZE=2] sender [/SIZE][SIZE=2]As[/SIZE][SIZE=2] ConnectedClient, [/SIZE][SIZE=2]ByVal[/SIZE][SIZE=2] message [/SIZE][SIZE=2]As[/SIZE][SIZE=2]String[/SIZE][SIZE=2])[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Sub[/SIZE][SIZE=2]New[/SIZE][SIZE=2]([/SIZE][SIZE=2]ByVal[/SIZE][SIZE=2] client [/SIZE][SIZE=2]As[/SIZE][SIZE=2] System.Net.Sockets.TcpClient, [/SIZE][SIZE=2]ByVal[/SIZE][SIZE=2] parentForm [/SIZE][SIZE=2]As[/SIZE][SIZE=2] Form1)[/SIZE][/COLOR]
[SIZE=2][COLOR=white]mParentForm = parentForm[/COLOR][/SIZE]
[SIZE=2][COLOR=white]mClient = client[/COLOR][/SIZE]
[COLOR=white][SIZE=2]readThread = [/SIZE][SIZE=2]New[/SIZE][SIZE=2] System.Threading.Thread([/SIZE][SIZE=2]AddressOf[/SIZE][SIZE=2] doRead)[/SIZE][/COLOR]
[COLOR=white][SIZE=2]readThread.IsBackground = [/SIZE][SIZE=2]True[/SIZE][/COLOR]
[SIZE=2][COLOR=white]readThread.Start()[/COLOR][/SIZE]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]Sub[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Public[/SIZE][SIZE=2]Property[/SIZE][SIZE=2] Username() [/SIZE][SIZE=2]As[/SIZE][SIZE=2]String[/SIZE][/COLOR]
[SIZE=2][COLOR=white]Get[/COLOR][/SIZE]
[COLOR=white][SIZE=2]Return[/SIZE][SIZE=2] mUsername[/SIZE][/COLOR]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]Get[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Set[/SIZE][SIZE=2]([/SIZE][SIZE=2]ByVal[/SIZE][SIZE=2] value [/SIZE][SIZE=2]As[/SIZE][SIZE=2]String[/SIZE][SIZE=2])[/SIZE][/COLOR]
[SIZE=2][COLOR=white]mUsername = value[/COLOR][/SIZE]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]Set[/SIZE][/COLOR]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]Property[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Private[/SIZE][SIZE=2]Sub[/SIZE][SIZE=2] doRead()[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Const[/SIZE][SIZE=2] BYTES_TO_READ [/SIZE][SIZE=2]As[/SIZE][SIZE=2]Integer[/SIZE][SIZE=2] = 255[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Dim[/SIZE][SIZE=2] readBuffer(BYTES_TO_READ) [/SIZE][SIZE=2]As[/SIZE][SIZE=2]Byte[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Dim[/SIZE][SIZE=2] bytesRead [/SIZE][SIZE=2]As[/SIZE][SIZE=2]Integer[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Dim[/SIZE][SIZE=2] sBuilder [/SIZE][SIZE=2]As[/SIZE][SIZE=2]New[/SIZE][SIZE=2] System.Text.StringBuilder[/SIZE][/COLOR]
[SIZE=2][COLOR=white]Do[/COLOR][/SIZE]
[SIZE=2][COLOR=white]bytesRead = mClient.GetStream.Read(readBuffer, 0, BYTES_TO_READ)[/COLOR][/SIZE]
[COLOR=white][SIZE=2]If[/SIZE][SIZE=2] (bytesRead > 0) [/SIZE][SIZE=2]Then[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Dim[/SIZE][SIZE=2] message [/SIZE][SIZE=2]As[/SIZE][SIZE=2]String[/SIZE][SIZE=2] = System.Text.Encoding.UTF8.GetString(readBuffer, 0, bytesRead)[/SIZE][/COLOR]
[COLOR=white][SIZE=2]If[/SIZE][SIZE=2] (message.IndexOf(MESSAGE_DELIMITER) > -1) [/SIZE][SIZE=2]Then[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Dim[/SIZE][SIZE=2] subMessages() [/SIZE][SIZE=2]As[/SIZE][SIZE=2]String[/SIZE][SIZE=2] = message.Split(MESSAGE_DELIMITER)[/SIZE][/COLOR]
[SIZE=2][COLOR=white]'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 [/COLOR][/SIZE]
[SIZE=2][COLOR=white]sBuilder.Append(subMessages(0))[/COLOR][/SIZE]
[COLOR=white][SIZE=2]RaiseEvent[/SIZE][SIZE=2] dataReceived([/SIZE][SIZE=2]Me[/SIZE][SIZE=2], sBuilder.ToString)[/SIZE][/COLOR]
[COLOR=white][SIZE=2]sBuilder = [/SIZE][SIZE=2]New[/SIZE][SIZE=2] System.Text.StringBuilder[/SIZE][/COLOR]
[SIZE=2][COLOR=white]'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: [/COLOR][/SIZE]
[COLOR=white][SIZE=2]If[/SIZE][SIZE=2] subMessages.Length = 2 [/SIZE][SIZE=2]Then[/SIZE][/COLOR]
[SIZE=2][COLOR=white]sBuilder.Append(subMessages(1))[/COLOR][/SIZE]
[SIZE=2][COLOR=white]Else[/COLOR][/SIZE]
[COLOR=white][SIZE=2]For[/SIZE][SIZE=2] i [/SIZE][SIZE=2]As[/SIZE][SIZE=2]Integer[/SIZE][SIZE=2] = 1 [/SIZE][SIZE=2]To[/SIZE][SIZE=2] subMessages.GetUpperBound(0) - 1[/SIZE][/COLOR]
[COLOR=white][SIZE=2]RaiseEvent[/SIZE][SIZE=2] dataReceived([/SIZE][SIZE=2]Me[/SIZE][SIZE=2], subMessages(i))[/SIZE][/COLOR]
[SIZE=2][COLOR=white]Next[/COLOR][/SIZE]
[SIZE=2][COLOR=white]sBuilder.Append(subMessages(subMessages.GetUpperBound(0)))[/COLOR][/SIZE]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]If[/SIZE][/COLOR]
[SIZE=2][COLOR=white]Else[/COLOR][/SIZE]
[SIZE=2][COLOR=white]'MESSAGE_DELIMITER was not found in the message, so we just append everything to the stringbuilder. [/COLOR][/SIZE]
[SIZE=2][COLOR=white]sBuilder.Append(message)[/COLOR][/SIZE]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]If[/SIZE][/COLOR]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]If[/SIZE][/COLOR]
[SIZE=2][COLOR=white]Loop[/COLOR][/SIZE]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]Sub[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Public[/SIZE][SIZE=2]Sub[/SIZE][SIZE=2] SendMessage([/SIZE][SIZE=2]ByVal[/SIZE][SIZE=2] msg [/SIZE][SIZE=2]As[/SIZE][SIZE=2]String[/SIZE][SIZE=2])[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Dim[/SIZE][SIZE=2] sw [/SIZE][SIZE=2]As[/SIZE][SIZE=2] IO.StreamWriter[/SIZE][/COLOR]
[SIZE=2][COLOR=white]Try[/COLOR][/SIZE]
[COLOR=white][SIZE=2]SyncLock[/SIZE][SIZE=2] mClient.GetStream[/SIZE][/COLOR]
[COLOR=white][SIZE=2]sw = [/SIZE][SIZE=2]New[/SIZE][SIZE=2] IO.StreamWriter(mClient.GetStream) [/SIZE][SIZE=2]'Create a new streamwriter that will be writing directly to the networkstream. [/SIZE][/COLOR]
[SIZE=2][COLOR=white]sw.Write(msg)[/COLOR][/SIZE]
[SIZE=2][COLOR=white]sw.Flush()[/COLOR][/SIZE]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]SyncLock[/SIZE][/COLOR]
[COLOR=white][SIZE=2]Catch[/SIZE][SIZE=2] ex [/SIZE][SIZE=2]As[/SIZE][SIZE=2] Exception[/SIZE][/COLOR]
[SIZE=2][COLOR=white]MessageBox.Show(ex.ToString)[/COLOR][/SIZE]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]Try[/SIZE][SIZE=2]'As opposed to writing to a file, we DONT call close on the streamwriter, since we dont want to close the stream. [/SIZE][/COLOR]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]Sub[/SIZE][/COLOR]
[COLOR=white][SIZE=2]End[/SIZE][SIZE=2]Class[/SIZE][/COLOR]
[COLOR=white]