Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ''' <summary>
- ''' The individual client class that is monitored by the server.
- ''' </summary>
- ''' <remarks></remarks>
- Public Class [Client]
- Implements IDisposable, IEqualityComparer
- 'Variables
- Private _client As TcpClient
- Private _thread As New Threading.Thread(AddressOf Read) With {.IsBackground = True}
- Private _disposed As Boolean = False
- 'User Variables; these are all serializable.
- Private _name As String = String.Empty
- Private _password As String = String.Empty
- Private _status As String = String.Empty
- Private _display As String = String.Empty
- Private _friends As New List(Of String)
- Private _ip As String = String.Empty
- 'Events
- Public Event Message(ByRef sender As Client, ByRef obj As Object)
- Public Event [Error](ByRef sender As Client, ByRef ex As Exception)
- Public Event Disconnected(ByVal sender As Client)
- 'Overridable Subs
- ''' <summary>
- ''' Called when the client has safely disconnected.
- ''' </summary>
- ''' <param name="ar">The IAsyncResult</param>
- ''' <remarks></remarks>
- Public Overridable Sub OnSafeDisconnect(ByVal ar As IAsyncResult)
- 'If the event completed, the client has disconnected.
- If ar.IsCompleted Then
- 'Raise the Disconnected Event.
- RaiseEvent Disconnected(Me)
- 'Save myself
- Me.Save()
- 'Reset.
- Me.Reset()
- End If
- End Sub
- 'Properties
- ''' <summary>
- ''' Gets or sets the client's name.
- ''' </summary>
- ''' <value></value>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Property Name As String
- Get
- Return _name
- End Get
- Set(ByVal value As String)
- _name = value
- End Set
- End Property
- ''' <summary>
- ''' Gets or sets the client's password.
- ''' </summary>
- ''' <value></value>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Property Password As String
- Get
- Return _password
- End Get
- Set(ByVal value As String)
- _password = value
- End Set
- End Property
- ''' <summary>
- ''' Gets or sets the client's status.
- ''' </summary>
- ''' <value></value>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Property Status As String
- Get
- Return _status
- End Get
- Set(ByVal value As String)
- _status = value
- 'ToDo: Client-side update/confirmation.
- End Set
- End Property
- ''' <summary>
- ''' Gets or sets the client's display name.
- ''' </summary>
- ''' <value></value>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Property Display As String
- Get
- Return _display
- End Get
- Set(ByVal value As String)
- _display = value
- 'ToDo: Client-side update/confirmation.
- End Set
- End Property
- ''' <summary>
- ''' Gets the IP Address of the Client.
- ''' </summary>
- ''' <value></value>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public ReadOnly Property IP As String
- Get
- 'If the IP Address hasn't been discovered, set it.
- If _ip.Equals(String.Empty) Then Me.GetIP()
- 'Return it.
- Return _ip
- End Get
- End Property
- ''' <summary>
- ''' Gets whether the Client is disposed or not.
- ''' </summary>
- ''' <value></value>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public ReadOnly Property Disposed As Boolean
- Get
- Return _disposed
- End Get
- End Property
- 'Subs
- ''' <summary>
- ''' Creates a blank Client Class.
- ''' </summary>
- ''' <remarks></remarks>
- Public Sub New()
- End Sub
- ''' <summary>
- ''' Creates a new Client Class that handles the client information.
- ''' </summary>
- ''' <param name="IncomingClient">The TcpClient to handle.</param>
- ''' <remarks></remarks>
- Public Sub New(ByRef IncomingClient As TcpClient)
- 'Get the Incoming Client.
- _client = IncomingClient
- 'Start the thread for reading.
- _thread.Start()
- 'Get the IP
- Me.GetIP()
- End Sub
- ''' <summary>
- ''' Listens for incoming messages to the stream.
- ''' </summary>
- ''' <remarks></remarks>
- Private Sub Read()
- 'It is in fact an infinite loop.
- Do While Not _disposed
- 'Create a try-catch block to trap any errors.
- Try
- 'Create the deserializer
- Dim Reader As New Binary.BinaryFormatter
- 'Create our generic object.
- Dim Obj As New Object
- 'Now sit on the stream and deserialize whatever comes through.
- Obj = Reader.Deserialize(_client.GetStream)
- 'Raise the event to pass the message up.
- RaiseEvent Message(Me, Obj)
- Catch tex As Threading.ThreadAbortException
- 'IGNORE THREAD ABORT.
- Exit Do
- Catch ex As Exception
- 'Some sort of error; but the client has to disconnect now.
- RaiseEvent Error(Me, ex)
- 'Exit the loop
- Exit Do
- End Try
- Loop
- End Sub
- ''' <summary>
- ''' Writes an object to the stream.
- ''' </summary>
- ''' <param name="obj">The object to write to the stream.</param>
- ''' <remarks></remarks>
- Public Sub Write(ByRef obj As Object)
- 'For errors.
- Try
- 'Create the writer.
- Dim Writer As New Binary.BinaryFormatter
- 'Now write it to the SyncLocked stream.
- SyncLock _client.GetStream
- Writer.Serialize(_client.GetStream, obj)
- End SyncLock
- 'No errors, success.
- Catch ex As Exception
- 'An error.
- RaiseEvent Error(Me, ex)
- End Try
- End Sub
- ''' <summary>
- ''' Disposes the Client and (tries) to release all utilized resources.
- ''' </summary>
- ''' <remarks></remarks>
- Private Sub Dispose() Implements IDisposable.Dispose
- 'If we aren't already disposed
- If Not Disposed Then
- 'Set our disposed variable to true.
- _disposed = True
- 'Kill the thread.
- _thread.Abort()
- 'Send a message to begin the disconnect.
- Me.Write(New ArkDLL.Disconnect)
- 'Begin the disconnection if we are not already disconnected
- If _client.Connected Then _client.Client.BeginDisconnect(False, New AsyncCallback(AddressOf OnSafeDisconnect), Nothing)
- End If
- End Sub
- ''' <summary>
- ''' Disposes the Client and (tries) to release all utilized resources.
- ''' </summary>
- ''' <param name="safe">If true, safely disconnect the client. If false, forcibly ends the connection.</param>
- ''' <remarks></remarks>
- Public Sub Dispose(ByVal safe As Boolean)
- 'Make sure we're not disposed already.
- If Disposed Then Return
- 'If we want to safely dispose of the object,
- 'Call the generic Me.Dispose.
- If safe Then Me.Dispose()
- 'Otherwise, forcibly terminate shit.
- _disposed = True
- 'Kill the reader thread.
- _thread.Abort()
- 'Dispose the client, ignore the exception.
- Try
- If _client.Connected Then _client.Client.Close()
- Catch ex As Exception
- End Try
- 'Save the user.
- Me.Save()
- 'Reset all variables
- Me.Reset()
- _client = Nothing
- _thread = Nothing
- 'Garbage Collect.
- GC.Collect()
- End Sub
- ''' <summary>
- ''' Resets the static variables.
- ''' </summary>
- ''' <remarks></remarks>
- Private Sub Reset()
- _name = String.Empty
- _display = String.Empty
- _friends.Clear()
- _ip = String.Empty
- _password = String.Empty
- _status = String.Empty
- End Sub
- ''' <summary>
- ''' Attempts to discover the IP address of the client.
- ''' </summary>
- ''' <remarks></remarks>
- Private Sub GetIP()
- Try
- Dim ipend As Net.IPEndPoint = CType(_client.Client.RemoteEndPoint, Net.IPEndPoint)
- If Not ipend Is Nothing Then _ip = ipend.Address.ToString
- Catch ex As System.ObjectDisposedException
- _ip = String.Empty
- RaiseEvent Error(Me, CType(ex, Exception))
- Catch ex As SocketException
- _ip = String.Empty
- RaiseEvent Error(Me, CType(ex, Exception))
- End Try
- End Sub
- ''' <summary>
- ''' Saves a Client to the system.
- ''' </summary>
- ''' <remarks></remarks>
- Public Sub Save()
- 'OK, format a path.
- Dim path As String = IO.Path.Combine(Application.StartupPath, "users")
- If Not Directory.Exists(path) Then Directory.CreateDirectory(path)
- 'Now, to save. 1) Create FileStream.
- Dim FS As New FileStream(String.Format("{0}\{1}.xml", path, Me.Name), FileMode.Create)
- 'Create the formatter
- Dim Saver As New Binary.BinaryFormatter
- 'Save!
- Saver.Serialize(FS, Me)
- 'Close the stream.
- FS.Close()
- End Sub
- ''' <summary>
- ''' Loads a Client from the system files.
- ''' </summary>
- ''' <param name="username">The username to load.</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function Load(ByVal username As String) As Client
- 'Format the filepath.
- Dim path As String = IO.Path.Combine(Application.StartupPath, "users")
- 'Loop the files in the directory.
- For Each File As String In IO.Directory.GetFiles(path)
- 'Get the filename.
- Dim Filename As String = IO.Path.GetFileNameWithoutExtension(File)
- 'Compare
- If Filename.Equals(username) Then
- 'Create a filestream.
- Dim FS As New FileStream(
- IO.Path.Combine(path, String.Format("{0}.xml", username)),
- FileMode.Open)
- 'Create a reader.
- Dim Reader As New Binary.BinaryFormatter
- 'Create the placeholder client.
- Dim Cli As New Client()
- 'Deserialize
- Cli = CType(Reader.Deserialize(FS), Client)
- 'Close the stream
- FS.Close()
- 'Return the client.
- Return Cli
- End If
- Next
- 'Found nothing, give back a blank client.
- Return New Client
- End Function
- ''' <summary>
- ''' Determines whether the specified objects are equal.
- ''' </summary>
- ''' <returns>
- ''' true if the specified objects are equal; otherwise, false.
- ''' </returns>
- ''' <param name="x">The first object to compare.</param>
- ''' <param name="y">The second object to compare.</param>
- ''' <exception cref="T:System.ArgumentException"><paramref name="x"/> and <paramref name="y"/> are of different types and neither one can handle comparisons with the other.</exception>
- Public Shadows Function Equals(ByVal x As Object, ByVal y As Object) As Boolean Implements IEqualityComparer.Equals
- 'Make sure they are both Client types.
- If x.GetType Is GetType(Client) AndAlso y.GetType Is GetType(Client) Then
- 'Convert them.
- Dim c1 As Client = CType(x, Client)
- Dim c2 As Client = CType(y, Client)
- 'And now compare.
- Return c1.Display.Equals(c2.Display) AndAlso c1.Name.Equals(c2.Display) AndAlso c1.Password.Equals(c2.Password) AndAlso c1.Status.Equals(c2.Status) AndAlso c1.IP.Equals(c2.IP)
- Else
- 'They are not proper objects, throw an exception.
- Throw New ArgumentException("In order to use the Equals function, both passed objects MUST be Clients!")
- End If
- End Function
- ''' <summary>
- ''' Returns a hash code for the specified object.
- ''' </summary>
- ''' <returns>
- ''' A hash code for the specified object.
- ''' </returns>
- ''' <param name="obj">The <see cref="T:System.Object"/> for which a hash code is to be returned.</param><exception cref="T:System.ArgumentNullException">The type of <paramref name="obj"/> is a reference type and <paramref name="obj"/> is null.</exception>
- Public Overloads Function GetHashCode(ByVal obj As Object) As Integer Implements IEqualityComparer.GetHashCode
- Throw New NotImplementedException()
- End Function
- ''' <summary>
- ''' Compares two Client classes to see if they are equal.
- ''' </summary>
- ''' <param name="one">The first client to compare.</param>
- ''' <param name="two">The second. client to compare.</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Shared Operator =(ByVal one As Client, ByVal two As Client) As Boolean
- 'Compare
- Return one.Equals(one, two)
- End Operator
- ''' <summary>
- ''' Compares two Client classes to see if they aren't equal.
- ''' </summary>
- ''' <param name="one">The first client to compare.</param>
- ''' <param name="two">The second. client to compare.</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Shared Operator <>(ByVal one As Client, ByVal two As Client) As Boolean
- 'Compare using the = method.
- Return Not one.Equals(one, two)
- End Operator
- End Class
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement