2013-12-20 64 views
0

我開始構建TCP服務器/客戶端及其協議,但他們有一些問題,我無法理解,因爲它沒有關於它的文檔,它也涉及進行交叉線程。我儘量避免非法跨線程。到目前爲止我的工作是在我的文本框中更新raiseStatus事件的狀態,無論如何我不知道如何使用listbox來完成它。通常我不能通過使用我建立的協議發送和接收所有的消息:LOGIN:NAK。這意味着用戶NAK登錄,我的程序可以很好地與這個協議進行通信,因爲我有更多的實現。當客戶端使用此命令時,我在將NAK添加到listbox1時遇到困難。Vb.net網絡編程不能添加新用戶到列表框

My Server and Client testing image:

我的服務器端代碼:

這是我的Form1類

Public Class Form1 

Dim portToListen As Integer = 700 
Dim WithEvents manager As ClientMananger 
Dim WithEvents M_Client As Client 

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load 
    manager = New ClientMananger(Me) 
    manager.Listen(portToListen) 

End Sub 

Private Sub manager_Status(message As String) Handles manager.Status 
    txtStatus.Text &= message & vbNewLine 
End Sub 

End Class 

,這是我的課ClientManager

Public Class ClientMananger 

Dim tcpListener As TcpListener 
Dim listenThread As Thread 

Dim clientList As New List(Of Client) 

Public Event Status(message As String) 
Public Event Connect(client As Client) 
Public Event Disconnect(client As Client) 

Public Sub Listen(port As Integer) 
    tcpListener = New TcpListener(port) 

    '' Start thread for listening for new income socket 
    listenThread = New Thread(AddressOf ListenProc) 
    listenThread.Start() 
End Sub 

Private Sub ListenProc() 
    RaiseStatus("Listen to port ...") 

    '' Continously listen to certain port 
    tcpListener.Start() 
    While True 
     Dim incomeClient As New Client(tcpListener.AcceptSocket(), Me) 

     '' Income connection has been made 
     RaiseStatus("Client attempt to connect ...") 

     '' Send welcome message to client 
     incomeClient.Send("Welcome to RAMA Hospital Chat Server!") 
     clientList.Add(incomeClient) 

    End While 
End Sub 

Public Sub SendAll(client As Client, msg As String) 
    For Each c As Client In clientList 
     If client IsNot c Then 
      c.Send(msg) 
     End If 
    Next 
End Sub 

Public Sub SendTo(sender As Client, rv As String, msg As String) 
    For Each c As Client In clientList 
     If c.name = rv Then 
      c.Send("PRIVATE:" & sender.name & ":" & msg) 
     End If 
    Next 
End Sub 

#Region "GUI" 
Dim form As Form 

'' GUI 
Public Sub New(form As Form) 
    Me.form = form 
End Sub 

Private Sub RaiseStatus(txt As String) 
    form.Invoke(RaiseStatusInvoker, txt) 
End Sub 

Private Delegate Sub RaiseStatusDelegate(txt As String) 
Private Sub RaiseStatusFunc(txt As String) 
    RaiseEvent Status(txt) 
End Sub 
Private RaiseStatusInvoker As New RaiseStatusDelegate(AddressOf RaiseStatusFunc) 

#End Region 

End Class 

而且這是類客戶端即我不能讓它工作,無論如何,我可以添加我的[部分(1)意味着我們ername從客戶端]部分(1)分配給listbox1?我用form1.listbox1.item.add(part(1)),但它不起作用它也不顯示任何錯誤。

Public Class Client 

Dim sck As Socket 
Dim msgThread As Thread 
Public name As String = "" 
Dim parent As ClientMananger 
Private _socket As Socket 
Private _client As Client 

Public Event Status(message As String) 

Public Sub New(sck As Socket, parent As ClientMananger) 
    Me.sck = sck 
    Me.parent = parent 

    '' Listen to incoming message 
    msgThread = New Thread(AddressOf ReceiveMessage) 
    msgThread.Start() 
End Sub 

Public Sub Send(message As String) 
    Dim msgByte() As Byte = System.Text.ASCIIEncoding.ASCII.GetBytes(message) 
    sck.Send(msgByte, SocketFlags.None) 
End Sub 

Private Sub ReceiveMessage() 
    Try 
     Dim buffer(1000) As Byte 
     Dim size As Integer = 0 
     Dim msg As String 

     Do 
      size = sck.Receive(buffer, SocketFlags.None) 
      If size > 0 Then 
       msg = System.Text.ASCIIEncoding.ASCII.GetString(buffer, 0, size) 
       HandleMessage(msg) 
      End If 
     Loop While size > 0 
    Catch ex As SocketException 
     '' Disconnect 
    End Try 
End Sub 

Private Sub HandleMessage(msg As String) 

    Dim part() As String = msg.Split(":") 
    Dim command As String = part(0).ToUpper() 

    If command = "LOGIN" Then 
     Me.name = part(1) 

     **Form1.listbox1.item.add(part(1))** 


     MessageBox.Show(part(1) + " Had been add to the server!!!") 
    ElseIf command = "ALL" Then 
     parent.SendAll(Me, part(1)) 
    ElseIf command = "PRIVATE" Then 
     parent.SendTo(Me, part(1), part(2)) 
    End If 

End Sub 
End Class 

對不起張貼大量的代碼,但真的不能做這項工作,請幫助THX你在前進,如果你想獲得我的客戶端代碼我可以在這裏發佈。

回答

1

編輯:

討論後,很顯然,你不能在這個方法從一個線程訪問一個列表框,它是不安全的每this article。相反,您必須使用ClientManager類中的狀態事件。您需要進行三個簡單的編輯:

首先,更新Form1中的狀態處理程序以將文本添加到新的列表框中。 (請相應地更改列表框名稱)

Private Sub manager_Status(message As String) Handles manager.Status 
    ' CODE ADDED 
    ' added code to add the text to a listbox, instead of a textbox 
    ListBox1.Items.Add(message) 
End Sub 

其次,使您的ClientManager RaiseStatus子項公開。它需要公開,所以客戶類可以在第三步中使用它。

' CODE ADDED 
' change access modifier to public 
Public Sub RaiseStatus(txt As String) 
    form.Invoke(RaiseStatusInvoker, txt) 
End Sub 

最後,更新客戶端Class.HandleMessage子使用父的RaiseStatus事件(你只是在最後一步向社會公佈了一個)M後

Private Sub HandleMessage(msg As String) 

    Dim part() As String = msg.Split(":") 
    Dim command As String = part(0).ToUpper() 

    If command = "LOGIN" Then 
     Me.name = part(1) 

     ' This is unsafe, you cannot access the parent thread this way 
     '**Form1.listbox1.item.add(part(1))** 

     ' CODE ADDED 
     ' this is safe, using the event handler. 
     ' parent.RaiseStatus("hello world") 
     parent.RaiseStatus(part(1)) 

    ElseIf command = "ALL" Then 
     parent.SendAll(Me, part(1)) 
    ElseIf command = "PRIVATE" Then 
     parent.SendTo(Me, part(1), part(2)) 
    End If 
End Sub 
+0

HI THX的幫助語法錯誤呢更改爲form1.listbox1.items.add(part(1))它在我的listbox1的列表項上沒有任何內容。 MessageBox.show()正確,但代碼現在無錯地添加,但仍不顯示結果。我認爲真正的問題不是那個錯誤。任何提示? –

+0

我用解決方案更新了這篇文章。 – laylarenee

相關問題