Vb.net 如何使用按钮关闭tcp客户端(client.close)?

Vb.net 如何使用按钮关闭tcp客户端(client.close)?,vb.net,multithreading,client-server,tcpclient,Vb.net,Multithreading,Client Server,Tcpclient,我有一个客户机-服务器应用程序 如果客户端已断开连接,服务器可以自动检测到它并将其从已连接客户端列表中删除 我现在将集中讨论服务器。 我想要一个停止服务器按钮。停止侦听器和Tcp客户端连接。 我可以很容易地停止侦听器,但我很难想出如何停止tcp客户端或发出客户端。关闭 [服务器] Public Class Server Dim ClientList As New Hashtable Dim Listener As TcpListener Dim ListenerThread As System.

我有一个客户机-服务器应用程序

如果客户端已断开连接,服务器可以自动检测到它并将其从已连接客户端列表中删除

我现在将集中讨论服务器。 我想要一个停止服务器按钮。停止侦听器和Tcp客户端连接。 我可以很容易地停止侦听器,但我很难想出如何停止tcp客户端或发出客户端。关闭

[服务器]

Public Class Server
Dim ClientList As New Hashtable
Dim Listener As TcpListener
Dim ListenerThread As System.Threading.Thread
Private Sub ButtonStart_Click(sender As Object, e As EventArgs) Handles ButtonStart.Click
    ListenerThread = New System.Threading.Thread(AddressOf Listen)
    ListenerThread.IsBackground = True
    ListenerThread.Start(TextBoxPort.Text)
    ButtonStart.Enabled = False
    ButtonStop.Enabled = True
    ListBox1.Items.Add("[SERVER] Waiting For A Connection...")
End Sub

Sub ClientDisconnected(ByVal Client As ConnectedClient) 
    ClientList.Remove(Client) 'remove the client from the hashtable
    ListBox2.Items.Remove(Client.Name) 'remove it from our listbox
End Sub

Sub Listen(ByVal Port As Integer)
    Try
        Listener = New TcpListener(IPAddress.Any, Port)
        Listener.Start()

        Do
            Dim Client As New ConnectedClient(Listener.AcceptTcpClient)
            AddHandler Client.ReceivedMessage, AddressOf ReceivedMessage
            AddHandler Client.ClientDisconnected, AddressOf ClientDisconnected
        Loop Until False
    Catch

    End Try
End Sub

Dim TotalItemCount As String
Sub ReceivedMessage(ByVal Msg As String, ByVal Client As ConnectedClient)
    Dim Message() As String = Msg.Split("|")
    Select Case Message(0)
        Case "CHAT" 'if it's CHAT
            ListBox1.Items.Add(Client.Name & " Says: " & " " & Message(1))

        Case "SAVETRAN"
            ListBox1.Items.Add("Transaction Number: " + Message(1) + vbCrLf + "Customer Number: " + Message(2))

        Case "TRANDETAIL"
            ListBox1.Items.Add("Barcode: " + Message(1) + vbCrLf + "Quantity: " + Message(2) + vbCrLf + "Price Sold: " + Message(3))
            ProgressBar1.Value += 1
            Label1.Text = ProgressBar1.Value

            If Label1.Text = ProgressBar1.Maximum Then
                ProgressBar1.Value = 0
            End If

        Case "ITEMCOUNT"
            ListBox1.Items.Add("SERVER IS EXPECTED TO RECEIVE " + Message(1) + " ITEMS.")
            TotalItemCount = Message(1)
            ProgressBar1.Maximum = TotalItemCount

        Case "LOGIN" 'A client has connected
            ClientList.Add(Client, Client.Name)
            ListBox2.Items.Add(Client.Name)
    End Select
End Sub

Private Sub ButtonStop_Click(sender As Object, e As EventArgs) Handles ButtonStop.Click

    Listener.Stop()

    ListBox1.Items.Add("Server Stopped")
    ButtonStop.Enabled = False
    ButtonStart.Enabled = True

End Sub

Private Sub Server_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    CheckForIllegalCrossThreadCalls = False
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    ListBox1.Items.Clear()
End Sub

End Class
在服务器应用程序中有一个类调用ConnectedClient

[连接的客户端]

Public Class ConnectedClient
Public Cli As TcpClient
Private UniqueID As String

Public Property Name

    Get
        Return UniqueID
    End Get
    Set(ByVal Value)
        UniqueID = Value
    End Set

End Property

Public Sub New(Client As TcpClient)
    Dim r As New Random
    Dim x As String = String.Empty

    For i = 0 To 7
        x &= Chr(r.Next(65, 89))
    Next
    Me.Name = Client.Client.RemoteEndPoint.ToString().Remove(Client.Client.RemoteEndPoint.ToString().LastIndexOf(":")) & " - " & x

    Cli = Client
    Cli.GetStream.BeginRead(New Byte() {0}, 0, 0, AddressOf Reading, Nothing)
End Sub

Public Event ReceivedMessage(ByVal Message As String, ByVal Client As ConnectedClient)

Public Event ClientDisconnected(ByVal Client As ConnectedClient)

Sub Reading(ByVal AR As IAsyncResult)
    Try
        Dim Reader As New StreamReader(Cli.GetStream)
        Dim Msg As String = Reader.ReadLine()
        RaiseEvent ReceivedMessage(Msg, Me)
        Cli.GetStream.BeginRead(New Byte() {0}, 0, 0, AddressOf Reading, Nothing)
    Catch ex As Exception
        'Try and read again

        Try
            Dim Reader As New StreamReader(Cli.GetStream)
            Dim Msg As String = Reader.ReadLine()
            RaiseEvent ReceivedMessage(Msg, Me)
            Cli.GetStream.BeginRead(New Byte() {0}, 0, 0, AddressOf Reading, Nothing)
        Catch
            RaiseEvent ClientDisconnected(Me)
        End Try
    End Try
End Sub

Sub SendData(ByVal Message As String)
    Dim Writer As New StreamWriter(Cli.GetStream)
    Writer.WriteLine(Message)
    Writer.Flush()
End Sub
End Class
我试图以某种方式链接到已连接的客户端类并获取client.Close,但我不能
找出答案。

服务器部分是主窗体线程,上面有所有按钮。只需在类级别上保留对ConnectedClient的引用列表,并在关闭服务器时为每个引用发出关闭。因此,在主窗体中,我将客户端设为连接客户端,并在哈希表中为每个客户端调用client.close。当我试图证明我得到的对象引用不是一个对象的实例。听起来很奇怪-你能提供更多关于你用来访问哈希表以关闭客户端的代码的细节吗?由于要在断开连接的事件中删除ConnectedClient,因此还必须确保在访问ConnectedClient哈希表时不会出现争用条件。