.NET 4.x Технология клиент-сервер. Классы клиента и сервера. Обсуждение - Visual Basic .NET

Узнай цену своей работы

Формулировка задачи:

В данном теме выкладываю свои классы клиента и сервера, а так же простеньких примеров реализованных на этих классах. Жду конструктивной критики, идей, предложений по улучшению, оптимизации и прочего.
Так же прошу поправлять меня, если комментарии в коде не соответствуют реальной действительности. Комментировал то как я это понимаю. P.S. с орфографией тоже туговато, так что исправляем
Листинг программы
  1. Imports System.Net.Sockets
  2. Public Class Class_Server
  3. Public Delegate Sub StatusInvoker(ByVal t As String) ' делегат для синхронизации при выводе сообщений
  4.  
  5. Private port As Integer = 13000 ' порт сервера на котором он работает
  6. Private server_name As String ' название сервера. Например: Game, Authorization server . Просто для удобства
  7. Private flag As Byte ' в текущий версии не используется. В будущем планируется клиентов с другим флагом сразу отключать, что бы только "правильные" клиенты могли подключаться к серверу.
  8. Private server_Listener As TcpListener ' Сам TcpListener который и прослушивает нужный порт
  9. Private clientsList As New Hashtable ' Список клиентов. (Уникальный индификатор ID,сам класс клиента)
  10. Public Event OnRead(ByVal _client As handleClinet, ByVal _data As String) ' Событие вызываемое при получении данных от клиентов
  11. Public Event Connect(ByVal _client As handleClinet) ' Событие вызываемое при подключении клиента
  12. Public Event Disconnect(ByVal _client As handleClinet, ByVal _reson As String) ' Событие вызываемое при отключении клиента
  13. Public Event messege(ByVal text As String) ' событие вызываемое, когда нужно передать информацию из класса
  14. Public Sub New(ByVal _Port As Integer, ByVal _Name As String, ByVal _Flag As Byte) ' инициализация класса. Порт, название, флаг
  15. port = _Port
  16. server_name = _Name
  17. flag = _Flag
  18. End Sub
  19. Public Sub start() ' Запуск сервера.
  20. Dim server_Thread As Threading.Thread = New Threading.Thread(AddressOf startServ)
  21. server_Thread.Start() ' Запуск отдельного потока на прослушивание порта и подключений к серверу
  22. End Sub
  23. Public Sub stop_server() ' Процедура для закрытия сервера.
  24. Dim Item As DictionaryEntry
  25. Dim list As Hashtable = clientsList
  26. For Each Item In list ' Перебор всех клиентов в списке
  27. CType(Item.Value, handleClinet).closeClient() ' Закрываем каждого клиента, что бы поток клиента завершился.
  28. Next
  29. server_Listener.Stop() ' Остановка прослушивания порта
  30. End Sub
  31. Public ReadOnly Property User_List() As Hashtable ' Возращаем список клиентов в виде хэш таблицы.
  32. Get
  33. Return clientsList
  34. End Get
  35. End Property
  36. Private Sub Client_OnRead(ByVal client As handleClinet, ByVal data As String) ' Процедура, вызываемая при получении сервером данных от клиента
  37. RaiseEvent OnRead(client, data) ' вызываем событие сервера, что клиент прислал данные
  38. End Sub
  39. Private Sub Client_Disconnect(ByVal client As handleClinet, ByVal reson As String) ' Процедура, вызываемая при отключении клиента
  40. clientsList.Remove(client.ID) ' удаляем клиента из списка клиентов
  41. RaiseEvent Disconnect(client, reson) ' вызываем событие сервера, что отключился клиент
  42. End Sub
  43. Public Sub Send_user(ByVal client As handleClinet, ByVal data As String) ' Процедура отправки данных нужному клиенту
  44. Dim tcp As TcpClient = client.TCP() ' получаем TcpClient нужный для получения потока записи
  45. Dim stream As NetworkStream = tcp.GetStream ' получение потока записи
  46. Dim mess() As Byte = System.Text.Encoding.UTF8.GetBytes(data) ' преобразование сообщения в байты для потока
  47. stream.Write(mess, 0, mess.Length) ' отсылка данных в виде байт
  48. stream.Flush() ' честно не знаю, что это делает. Работает и с этим и без, но в большинстве примеров есть, поэтому оставил.
  49. End Sub
  50. Public Sub Send_all(ByVal data As String) ' Процедура посылки сообщения всем клиентам
  51. Dim Item As DictionaryEntry
  52. Dim list As Hashtable = clientsList
  53. For Each Item In list ' Перебор всех клиентов и рассылка через Send_user
  54. Send_user(CType(Item.Value, handleClinet), data)
  55. Next
  56. End Sub
  57.  
  58. Private Sub startServ() ' процедура служащая для прослушивания порта и подключении клиентов
  59. Dim client As TcpClient
  60. Dim count As Integer ' Кол-во подключений
  61. Try
  62. server_Listener = New TcpListener(port)
  63. server_Listener.Start() ' Начинаем прослушивать порт
  64. msg("=========Сервер " & Me.server_name & " запущен...=========")
  65.  
  66. While True ' Бесконечный цикл, что бы клиенты могли подключаться всегда
  67. count += 1 ' Новое подключение, значит счетчик +1
  68. client = server_Listener.AcceptTcpClient() ' Ждем подключения. Когда клиент подключается, запоминаем его в client
  69. Dim temp_client As New handleClinet(client, count) ' Создаем новый класс клиента и передаем ему подключившегося клиента и его номер подключения
  70. temp_client.startClient(Me) ' Запускаем клиента и прослушивание входящих сообщений. Ссылку на класс сервера передаем, что бы клиент мог добавить своё событие на Client_OnRead
  71. clientsList.Add(temp_client.ID, temp_client) ' Добавляем клиента в список клиентов
  72. RaiseEvent Connect(temp_client) ' Вызываем событие, что клиент подключился
  73. End While
  74. Catch ex As Exception
  75. msg("=========Ошибка сервера " & Me.server_name & ". Причина: " & ex.Message) ' Сообщаем об ошибке
  76. End Try
  77. ' Так как сюда попасть можно, только после ошибки, значит сервер остановлен. Сообщаем об этом.
  78. msg("=========Сервер " & Me.server_name & " остановлен!=========")
  79. End Sub
  80. Public Sub msg(ByVal t As String) ' Процедура отправки сообщения
  81. Try
  82. RaiseEvent messege(t) ' Вызываем событие о новом сообщении
  83. Catch ex As Exception
  84. MsgBox(ex.Message, , "Msg Сервера")
  85. End Try
  86. End Sub
  87.  
  88. Public Class handleClinet ' Класс клиента в сервере. Нужен для индификации и базовых дейсвий с клиентом
  89. Public Event OnRead(ByVal _client As handleClinet, ByVal _data As String) ' Событие, что текущий клиент получил данные
  90. Public Event Disconnect(ByVal _client As handleClinet, ByVal _reson As String) ' Событие при отключении текущего клиента
  91. Private mgID As Guid = Guid.NewGuid ' Получаем уникальный индификатор клиента для хэш таблицы списка клиентов
  92. Private clientSocket As TcpClient ' Сокет клиента
  93. Private stream As NetworkStream ' Поток данных клиента
  94. Private clNo As String ' Номер клиента
  95. ' Private serv As Class_Server
  96. Private myIP As String ' Храним тут ип этого клиента
  97. Public Sub New(ByVal inClientSocket As TcpClient, ByVal count As Integer) ' Инициализация клиента
  98. Me.clientSocket = inClientSocket
  99. Me.stream = clientSocket.GetStream()
  100. Me.clNo = count
  101. End Sub
  102. Public ReadOnly Property IP() As String ' Получение IP
  103. Get
  104. If myIP = "" Then myIP = clientSocket.Client.RemoteEndPoint.ToString
  105. Return myIP
  106. End Get
  107. End Property
  108. Public ReadOnly Property ID() As String ' Получение ID
  109. Get
  110. Return mgID.ToString
  111. End Get
  112. End Property
  113. Public ReadOnly Property Number() As String ' Получение номера клиента
  114. Get
  115. Return clNo.ToString
  116. End Get
  117. End Property
  118. Public ReadOnly Property TCP() As TcpClient ' Получение TcpClient клиента
  119. Get
  120. Return clientSocket
  121. End Get
  122. End Property
  123. Public Sub closeClient() ' Процедура принудительного закрытия подключения клиента
  124. stream.Close()
  125. clientSocket.Close()
  126. End Sub
  127. Public Sub startClient(ByVal _serv As Class_Server) ' Процедура запуска клиента
  128. Dim client_Thread As Threading.Thread = New Threading.Thread(AddressOf doListen)
  129. client_Thread.Start() ' Запуск прослушивания новых данных текущим клиентом в отедьном потоке
  130. AddHandler Me.OnRead, AddressOf _serv.Client_OnRead ' При срабатывании события OnRead в клиенте, вызываем процедуру Client_OnRead на самом сервере
  131. AddHandler Me.Disconnect, AddressOf _serv.Client_Disconnect ' При срабатывании события Disconnect в клиенте, вызываем процедуру Client_Disconnect на самом сервере
  132. End Sub
  133. Private Sub doListen()
  134. Dim bytes(1048576) As Byte ' 1мб буфер, что бы данные не дробились.
  135. Dim data As String
  136. Dim i As Int32
  137. Try
  138. i = stream.Read(bytes, 0, bytes.Length) ' Ждем новых данных от клиентского приложения. При получении заносим данные в буфер bytes и длину данных в i
  139. While (i <> 0) ' Цикл бесконечный, пока длина считанных данных не окажется=0, что ознает, что клиент оключился.
  140. data = System.Text.Encoding.UTF8.GetString(bytes, 0, i) ' Переводим байты в текст
  141. RaiseEvent OnRead(Me, data) ' Вызываем событие о получении новых данных
  142. i = stream.Read(bytes, 0, bytes.Length) ' Ждем новых данных от клиентского приложения. При получении заносим данные в буфер bytes и длину данных в i
  143. End While
  144. closeClient() ' Так как вышли из цикла, то клиентское приложение закрыло соединение. Следовательно закрываем и мы.
  145. RaiseEvent Disconnect(Me, "Клиент решил отключиться от сервера.") ' Вызываем событие, что клиент отключился и передаем причину.
  146. Catch ex As Exception
  147. closeClient() ' Ошибка, значит отключаем клиента.
  148. RaiseEvent Disconnect(Me, "Проблема соединения: " & ex.Message) ' Вызываем событие, что клиент отключился и передаем причину.
  149. End Try
  150. End Sub
  151. End Class
  152. End Class
Листинг программы
  1. Imports System.Net.Sockets
  2. Public Class Class_client
  3. Public Delegate Sub StatusInvoker(ByVal t As String) ' делегат для синхронизации при выводе сообщений
  4. Dim client As TcpClient ' Текущий TcpClient связывающий клиента и сервер
  5. Dim stream As NetworkStream ' Поток данных связывающий клиента и сервер
  6. Dim flag As Byte ' Пока не используется. Нужен для индификации сервером "правильного" клиента
  7. Dim connection As Boolean = False ' Состояние подключения
  8.  
  9. Public Event OnRead(ByVal _data As String) ' Событие, при получении данных от сервера
  10. Public Event Disconnected(ByVal _reson As String) ' Событие, при отключении от сервера
  11. Public Event messege(ByVal text As String) ' Событие, при необходимости передать сообщение из класса
  12. Dim s As Object
  13. Public Function Connect(ByVal server As String, ByVal port As Integer, ByVal _Flag As Byte) As Boolean ' Функция подключения клиента к серверу. Вернет True в случае удачи и False при ошибке.
  14. If connection = False Then ' Проверка не подключены ли мы уже?
  15. Try
  16. Me.client = New TcpClient(server, port)
  17. Me.stream = client.GetStream()
  18. Me.flag = _Flag
  19. Dim client_Thread As Threading.Thread = New Threading.Thread(AddressOf Me.doListen)
  20. client_Thread.Start() ' Запуск отдельного потока на прослушивание данных с сервера.
  21. connection = True ' Состояние=Подключен
  22. Return True
  23. Catch ex As Exception
  24. msg(ex.Message) ' Сообщаем об ошибке
  25. Return False
  26. End Try
  27. Else
  28. Return False ' Если уже подключены, тогда новое подключение не удалось
  29. End If
  30. End Function
  31. Public Sub Disconnect(Optional ByVal s As String = "") ' Процедура отключения от сервера. Возможно указать коментарий.
  32. If connection Then
  33. connection = False ' Состояние=Отключен
  34. stream.Close()
  35. client.Close()
  36. If s = "" Then
  37. RaiseEvent Disconnected("Отключен") ' Вызываем событие отключения с коментарием "по умолчанию"
  38. Else
  39. RaiseEvent Disconnected(s) ' Вызываем событие отключения с коментарием указанным при вызове текущей процедуры
  40. End If
  41. End If
  42. End Sub
  43. Public Function Send(ByVal data As String) As Boolean ' Функция отправки сообщения серверу. Вернет True, если посылка удалась или False в обратном случаее
  44. If connection Then
  45. Try
  46. Dim databyte() As Byte = System.Text.Encoding.UTF8.GetBytes(data) ' Создаем массив байтов для отправки из Data
  47. stream.Write(databyte, 0, databyte.Length) ' Отправляем наш массив байт.
  48. stream.Flush() ' честно не знаю, что это делает. Работает и с этим и без, но в большинстве примеров есть, поэтому оставил.
  49. Return True ' Говорим, что посылка удалась
  50. Catch ex As Exception
  51. msg(ex.Message) ' Сообщаем об ошибке
  52. Disconnect("Проблема при отправке.") ' Отключаемся
  53. Return False
  54. End Try
  55. Else
  56. Return False ' Если не подключены, то отправка не удалась.
  57. End If
  58. End Function
  59.  
  60. Private Sub doListen() ' Процедура прослушки сообщений от сервера
  61.  
  62. Dim bytes(1048576) As Byte ' 1мб буфер, чтобы данные не дробились.
  63. Dim data As String
  64. Dim i As Int32
  65. Try
  66. i = stream.Read(bytes, 0, bytes.Length) ' Ждем новых данных от сервера. При получении заносим данные в буфер bytes и длину данных в i
  67. While (i <> 0) ' Цикл бесконечный, пока длина считанных данных не окажется=0, что ознает, что соединение с сервером прекращенно.
  68. data = System.Text.Encoding.UTF8.GetString(bytes, 0, i) ' Переводим байты в текст
  69. RaiseEvent OnRead(data) ' Вызываем событие о получении новых данных
  70. i = stream.Read(bytes, 0, bytes.Length) ' Ждем новых данных от сервера. При получении заносим данные в буфер bytes и длину данных в i
  71. End While
  72. Disconnect() ' Так как вышли из цикла, то сервер закрыло соединение. Следовательно отключаемся.
  73. Catch ex As Exception
  74. Disconnect(ex.Message) ' Ошибка, значит отключаемся, указав причину.
  75. End Try
  76. End Sub
  77.  
  78. Public Sub msg(ByVal t As String) ' Процедура отправки сообщения
  79. Try
  80. RaiseEvent messege(t) ' Вызываем событие о новом сообщении
  81. Catch ex As Exception
  82. MsgBox(ex.Message)
  83. End Try
  84. End Sub
  85. End Class
Сообщение в разработке. Примеры будут чуть позже.

Решение задачи: «.NET 4.x Технология клиент-сервер. Классы клиента и сервера. Обсуждение»

textual
Листинг программы
  1. Public Sub Send_user(ByVal client As handleClinet, ByVal data As String) ' Процедура отправки данных нужному клиенту
  2.         Dim tcp As TcpClient = client.TCP() ' получаем TcpClient нужный для получения потока записи
  3.         Dim stream As NetworkStream = tcp.GetStream ' получение потока записи
  4.  
  5.         Dim mess() As Byte = System.Text.Encoding.UTF8.GetBytes(data) ' преобразование сообщения в байты для потока
  6.  
  7.         stream.Write(mess, 0, mess.Length) ' отсылка данных в виде байт
  8.         stream.Flush() ' честно не знаю, что это делает. Работает и с этим и без, но в большинстве примеров есть, поэтому оставил.
  9.     End Sub

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

12   голосов , оценка 3.75 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы