У меня есть класс под названием SocketSvr, который обрабатывает асинхронный сервер сокетов. Он вызывается через BackgroundWorker из моей основной формы. По сути, я просто хочу, чтобы он отображал информацию о моих сокетах внутри текстового поля в главной форме, и чтобы кнопка «Пуск / Стоп» сервера была доступна в главной форме для выполнения этих задач.
Вот код из Form1.vb:
Public Class Form1
Dim WithEvents Socketsvr As New SocketSvr
Private Sub ToggleServerButton_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles ToggleServerButton.Click
If ToggleServerButton.Text = "Stop Server" Then
ToggleServerButton.Text = "Start Server"
Socketsvr.StopServer()
Else
ToggleServerButton.Text = "Stop Server"
Socketsvr.StartServer()
End If
End Sub
Private Sub UpdateOutput_Event(ByVal sender As Object, _
ByVal text As String) Handles Socketsvr.UpdateOutput
Me.ServerOutputTextbox.AppendText(text + vbCrLf)
End Sub
End Class
Выше очень просто, в основном вызывает функции StartServer () или StopServer (). Событие ниже является событием Raised, которое я использую для обновления текстового поля с помощью вызванного события из фонового процесса.
Ниже приведен код кода для Socketsvr.vb - я удалил нерелевантный код, чтобы свести к минимуму взлом поста.
Public Sub StopServer()
bw.CancelAsync()
allDone.Set()
End Sub 'StopServer
Public Sub StartServer()
bw.WorkerSupportsCancellation = True
bw.RunWorkerAsync()
End Sub 'StartServer
Private Sub bw_DoWork(ByVal sender As System.Object, _
ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bw.DoWork
' Data buffer for incoming data.
Dim bytes() As Byte = New [Byte](1023) {}
' Establish the local endpoint for the socket.
Dim ipHostInfo As New IPHostEntry
ipHostInfo.AddressList = New IPAddress() _
{New IPAddress(New [Byte]() {127, 0, 0, 1})}
Dim ipAddress As IPAddress = ipHostInfo.AddressList(0)
Dim localEndPoint As New IPEndPoint(ipAddress, 8888)
' Create a TCP/IP socket.
Dim listener As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
' Bind the socket to the local endpoint and listen for incoming connections.
listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1)
listener.Bind(localEndPoint)
listener.Listen(100)
While True
' If cancellation is pending, shut down server
If bw.CancellationPending Then
Out("Server stopped at " + DateTime.Now.ToString())
Exit While
End If
Out("Server started at " + DateTime.Now.ToString())
' Set the event to nonsignaled state.
allDone.Reset()
Try
' Start an asynchronous socket to listen for connections.
listener.BeginAccept(New AsyncCallback(AddressOf AcceptCallback), listener)
Catch ex As Exception
MessageBox.Show(ex.ToString, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
' Wait until a connection is made and processed before continuing.
allDone.WaitOne()
End While
End Sub
Я не уверен, как правильно завершать запросы от клиента при запуске функции StopServer (). В приведенном выше коде я помещаю очередь отмены для фонового процесса. Самое смешное, что после запуска StopServer () он примет еще одно соединение, а затем перестанет его принимать.
Если я уберу следующую строку из кода выше:
listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1)
- происходит сбой, когда я пытаюсь запустить сервер во второй раз (жалуясь, что я не могу повторно использовать сокет, очевидно) Я предполагаю, что мне нужно добавить что-то к вызову bw.CancellationPending на фоновом работнике?
Буду признателен за любую информацию, пожалуйста, дайте мне знать, если от меня потребуется больше информации.