ClientForm.vb 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. Imports System.Net
  2. Imports System.Net.Sockets
  3. Public Class ClientForm
  4. Private _Connection As ConnectionInfo
  5. Private _ServerAddress As IPAddress
  6. Private Sub ClientForm_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
  7. ValidateChildren()
  8. End Sub
  9. Private Sub ConnectButton_CheckedChanged(sender As Object, e As System.EventArgs) Handles ConnectButton.CheckedChanged
  10. If ConnectButton.Checked Then
  11. If _ServerAddress IsNot Nothing Then
  12. ConnectButton.Text = "Disconnect"
  13. ConnectButton.Image = My.Resources.Disconnect
  14. Try
  15. _Connection = New ConnectionInfo(_ServerAddress, CInt(PortTextBox.Text), AddressOf InvokeAppendOutput)
  16. _Connection.AwaitData()
  17. Catch ex As Exception
  18. MessageBox.Show(ex.Message, "Error Connecting to Server", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
  19. ConnectButton.Checked = False
  20. End Try
  21. Else
  22. MessageBox.Show("Invalid server name or address.", "Cannot Connect to Server", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
  23. ConnectButton.Checked = False
  24. End If
  25. Else
  26. ConnectButton.Text = "Connect"
  27. ConnectButton.Image = My.Resources.Connect
  28. If _Connection IsNot Nothing Then _Connection.Close()
  29. _Connection = Nothing
  30. End If
  31. End Sub
  32. Private Sub SendButton_Click(sender As System.Object, e As System.EventArgs) Handles SendButton.Click
  33. If _Connection IsNot Nothing AndAlso _Connection.Client.Connected AndAlso _Connection.Stream IsNot Nothing Then
  34. Dim buffer() As Byte = System.Text.Encoding.ASCII.GetBytes(InputTextBox.Text)
  35. _Connection.Stream.Write(buffer, 0, buffer.Length)
  36. End If
  37. End Sub
  38. Private Sub ServerTextBox_Validating(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles ServerTextBox.Validating
  39. _ServerAddress = Nothing
  40. Dim remoteHost As IPHostEntry = Dns.GetHostEntry(ServerTextBox.Text)
  41. If remoteHost IsNot Nothing AndAlso remoteHost.AddressList.Length > 0 Then
  42. For Each deltaAddress As IPAddress In remoteHost.AddressList
  43. If deltaAddress.AddressFamily = AddressFamily.InterNetwork Then
  44. _ServerAddress = deltaAddress
  45. Exit For
  46. End If
  47. Next
  48. End If
  49. If _ServerAddress Is Nothing Then
  50. MessageBox.Show("Cannot resolove server address.", "Invalid Server", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
  51. ServerTextBox.SelectAll()
  52. e.Cancel = True
  53. End If
  54. End Sub
  55. Private Sub PortTextBox_Validating(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles PortTextBox.Validating
  56. Dim deltaPort As Integer
  57. If Not Integer.TryParse(PortTextBox.Text, deltaPort) OrElse deltaPort < 1 OrElse deltaPort > 65535 Then
  58. MessageBox.Show("Port number must be an integer between 1 and 65535.", "Invalid Port Number", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
  59. PortTextBox.SelectAll()
  60. e.Cancel = True
  61. End If
  62. End Sub
  63. 'The InvokeAppendOutput method could easily be replaced with a lambda method passed
  64. 'to the ConnectionInfo contstructor in the ConnectButton_CheckChanged event handler
  65. Private Sub InvokeAppendOutput(message As String)
  66. Dim doAppendOutput As New Action(Of String)(AddressOf AppendOutput)
  67. Me.Invoke(doAppendOutput, message)
  68. End Sub
  69. Private Sub AppendOutput(message As String)
  70. If RichTextBox1.TextLength > 0 Then
  71. RichTextBox1.AppendText(ControlChars.NewLine)
  72. End If
  73. RichTextBox1.AppendText(message)
  74. RichTextBox1.ScrollToCaret()
  75. End Sub
  76. End Class
  77. 'Encapuslates the client connection and provides a state object for async read operations
  78. Public Class ConnectionInfo
  79. Private _AppendMethod As Action(Of String)
  80. Public ReadOnly Property AppendMethod As Action(Of String)
  81. Get
  82. Return _AppendMethod
  83. End Get
  84. End Property
  85. Private _Client As TcpClient
  86. Public ReadOnly Property Client As TcpClient
  87. Get
  88. Return _Client
  89. End Get
  90. End Property
  91. Private _Stream As NetworkStream
  92. Public ReadOnly Property Stream As NetworkStream
  93. Get
  94. Return _Stream
  95. End Get
  96. End Property
  97. Private _LastReadLength As Integer
  98. Public ReadOnly Property LastReadLength As Integer
  99. Get
  100. Return _LastReadLength
  101. End Get
  102. End Property
  103. Private _Buffer(63) As Byte
  104. Public Sub New(address As IPAddress, port As Integer, append As Action(Of String))
  105. _AppendMethod = append
  106. _Client = New TcpClient
  107. _Client.Connect(address, port)
  108. _Stream = _Client.GetStream
  109. End Sub
  110. Public Sub AwaitData()
  111. _Stream.BeginRead(_Buffer, 0, _Buffer.Length, AddressOf DoReadData, Me)
  112. End Sub
  113. Public Sub Close()
  114. If _Client IsNot Nothing Then _Client.Close()
  115. _Client = Nothing
  116. _Stream = Nothing
  117. End Sub
  118. Private Sub DoReadData(result As IAsyncResult)
  119. Dim info As ConnectionInfo = CType(result.AsyncState, ConnectionInfo)
  120. Try
  121. If info._Stream IsNot Nothing AndAlso info._Stream.CanRead Then
  122. info._LastReadLength = info._Stream.EndRead(result)
  123. If info._LastReadLength > 0 Then
  124. Dim message As String = System.Text.Encoding.ASCII.GetString(info._Buffer)
  125. info._AppendMethod(message)
  126. End If
  127. info.AwaitData()
  128. End If
  129. Catch ex As Exception
  130. info._LastReadLength = -1
  131. info._AppendMethod(ex.Message)
  132. End Try
  133. End Sub
  134. End Class