Die Community zu .NET und Classic VB.
Menü

Winsock Programmierung

 von 

Einleitung 

Wenn man mich bisher gefragt hat, wie man mit dem Winsock-Control umgeht habe ich immer geantwortet "Suche in der MSDN nach Chat". Doch mittlerweile wurde mir gesagt, dass diese Samples da nicht unbedingt einfach zu verstehen seien. Auch wird die Möglichkeit, mehrere Benutzer gleichzeitig zu "verarbeiten" nur am Rande erwähnt. Einen Chat, der mehrere Benutzer zulässt werde ich in der nächsten Folge zeigen.

Mit freundlichen Grüßen
Patrice Neff

Listen und Connect  

Um mit dem Winsock-Control umgehen zu können ist das Verständnis zweier Methoden wichtig. Es geht um die Methoden Connect und Listen . Die Methode Listen wird verwendet, um als Server zu fungieren. Die Methode Connect um zu einem Server zu verbinden. Ich verwende dafür normalerweise die folgende Vorstellung: Ein Webserver wird beim Programmstart ein Listen im Code enthalten.

Während ein Browser bei jedem Zugriff auf eine Website einen Connect ausführt. Im Multi-User-Chat, den ich in der nächsten Folge zeigen werde, sieht das dann so aus, dass ein Benutzer als Server fungiert. Diese Programminstanz wird die Methode Listen verwenden. Alle User, die nun an dem Chat teilnehmen wollen, werden einen Connect ausführen müssen.

Senden von Daten  

Nachdem eine Verbindung besteht (dazu nachher mehr) können Daten ausgetauscht werden. Die geschieht sehr einfach mit der Methode SendData, welcher die zu sendenden Daten als String übergeben werden. Allerdings gibt es hier einige Tücken zu beachten. Wenn diese Funktion in einer Schleife x-mal nacheinander ausgeführt wird, kommt es zu Fehlern. Denn beim Senden der Daten kann (und wird es im Allgemeinen) zu Verzögerungen kommen. Deshalb arbeite ich mit einer Funktion, welche eine Pause einlegt, bis die Daten wirklich gesendet sind. Diese Funktion sieht folgendermaßen aus:

Private Sub Senden(strData As String)
    blnSendCompleted = False
    wsckChat.SendData strData
    Do Until blnSendCompleted
        DoEvents
    Loop
End Sub

Erklärungen: Die Variable blnSendCompleted ist im Formular-Kopf als Boolean definiert. Diese wird in der Sub wsckChat_SendComplete auf True gesetzt. Das Event SendComplete des Winsock-Controls wird ausgelöst, wenn die Daten fertig gesendet sind. Das ist die beste mir bekannte Möglichkeit, für das Senden von Daten.

Nachrichten anzeigen  

In diesem Beispiel wird für das Anzeigen von Nachrichten eine Multiline-TextBox verwendet. Das ist zwar keine sehr komfortable Lösung, aber auch nicht wirklich schlecht. Und schließlich soll es ja nur ein Beispiel sein ;-) Auch das Anzeigen von Nachrichten wurde in eine Sub ausgelagert:

Private Sub AddMessage(strMessage As String, strSender As String)
    txtChat.Text = txtChat.Text & _ "(" & _
    Trim(strSender) & ") " & _ strMessage & vbCrLf
    txtChat.SelStart = Len(txtChat.Text)
End Sub

Erklärungen: Dieser Code ist nicht sonderlich aufregend. Als erstes wird der neue Text inklusive Absender in der TextBox ans Ende geschrieben. Danach wird noch sichergestellt, dass auch das Ende der TextBox sichtbar ist.

Die Methode Listen verwenden  

Nun sind wir soweit. Wenn der Benutzer auf den Button cmdListen klickt, soll das Programm soweit vorbereitet werden, dass ein anderer Benutzer connecten kann. Stell dir das aber nicht zu schwierig vor. Der folgende Code ist nötig:

Private Sub cmdListen_Click()
    strNick = Left(txtName & Space(50), 50)
    wsckChat.LocalPort = 12123
    wsckChat.Listen
End Sub

Erklärungen: Die erste Zeile hat nur die Aufgabe, in der Variable strNick den Nick zu speichern, der im Chat verwendet wird. Für den Chat absolut nötig, und deshalb auch interessant, sind nur die beiden letzten Zeilen. Die Eigenschaft LocalPort legt fest, auf welchem Port das Programm laufen soll. Die Ports sind nötig, um verschiedenen Netzwerk-Programme auf einem Rechner aufs mal laufen lassen zu können. Oder hast du schon mal ernsthaft überlegt, wie das Betriebssystem denn weiß, dass die reinkommenden Daten jetzt für dem Browser und nicht dem Mail-Client sind? Das geschieht durch die verschiedenen Ports (Beim Web-Server z.B. meistens der Port 80) Die Methode Listen sagt schließlich, dass das Programm jetzt bitte auf eine reinkommende Verbindung warten soll.

Kontaktaufnahme  

Wenn wir jetzt die Methode Listen aufgerufen haben, kann man noch nicht chatten. Schließlich muss erst ein anderer Rechner Kontakt aufnehmen. Das geschieht über die Methode Connect (kommt weiter unten). Wenn nun ein Client Kontakt aufnimmt, feuert das Winsock-Control das Event ConnectionRequest. Der Code sieht folgendermaßen aus:

Private Sub wsckChat_ConnectionRequest(ByVal requestID As Long)
If wsckChat.State = sckListening Then
wsckChat.Close
wsckChat.Accept requestID 
MsgBox "Es wurde eine Verbindung aufgenommen"
End If
End Sub

Erklärungen: Die IF-Abfrage dient dazu, Fehler zu verhindern. Hinweise dazu findest du im kommentierten Quellcode. Wichtig ist die Methode Accept. Mit der wird eine reinkommende Verbindung angenommen.

Server und Client  

Was nützt mir ein Server ohne Client ?

Die Antwort ist "Rein gar nix". Deshalb wollen wir uns mal an den Client-Part machen. Da kommt die oft erwähnte Methode Connect zum Einsatz.

Private Sub cmdConnect_Click()
    Dim strRemoteComputer As String
    strNick = Left(txtName & Space(50), 50)
    strRemoteComputer = InputBox("RemoteHost:")
    If Trim(strRemoteComputer) = "" Then Exit Sub
    wsckChat.RemotePort = 12123
    wsckChat.RemoteHost = strRemoteComputer
    wsckChat.Connect
End Sub

Erklärungen: Um mit einem anderen PC zu connecten, muss natürlich dessen IP bekannt sein. Die IP wird über die InputBox eingegeben. Die Eigenschaft RemoteHost gibt an, zu welchem Rechner verbunden werden soll. Danach muss dem Winsock-Control bekannt gegeben werden, auf welchem Port es verbinden soll. Die Eigenschaft RemotePort ist dafür zuständig. Der Wert, welcher hier verwendet wird, muss gleich sein, wie der Wert LocalPort, bei Listen. Nachdem diese beiden Eigenschaften gesetzt wurden, wird die Methode Connect aufgerufen. (Anmerkung: Die beiden Werten könnten auch direkt der Methode übergeben werden. Das habe ich hier aber aus Lernzwecken nicht so gelöst) Das Programm ist jetzt soweit, dass zwei Rechner miteinander Kontakt aufnehmen können. Allerdings werden noch keine Nachrichten gesendet bzw. ausgewertet. Das folgt in den beiden nächsten Abschnitten.

Nachrichten senden  

Am Anfang dieses Tutorials habe ich die Sub Senden vorgestellt. Diese soll nun verwendet werden. Folgender Code ist für den Button cmdSend nötig.

Private Sub cmdSend_Click()
Dim strMessage As String
strMessage = strNick & _ txtNachricht.Text
Senden strMessage
AddMessage txtNachricht.Text, strNick
End Sub

Erklärungen: In der Sub wird erst die Nachricht zusammengebaut. Danach wird sie versendet, und zuletzt wird der Text noch im Chat-Fenster angezeigt. Übers Netzwerk gesendet werden immer der Nick und die Nachricht.

Nachrichten empfangen  

Die Nachrichten werden zwar versendet, aber sie werden noch nicht angezeigt. So bringt uns der Chat natürlich nicht sehr viel. Aber mit dem folgenden Code wird alles gut... ;-)

Private Sub wsckChat_DataArrival(ByVal bytesTotal As Long)
Dim strData As String
Dim strNick As String
Dim strMessage As String
wsckChat.GetData strData
strNick = Trim(Mid(strData, 1, 50))
strMessage = Mid(strData, 51)
AddMessage strMessage, strNick
End Sub

Erklärungen: Das Event DataArrival wird immer ausgelöst, wenn Daten reinkommen. Hier müssen die Daten entgegengenommen und verarbeitet werden. Ins Programm rein bekommen wir die Daten mit der Methode GetData. Dieser wird eine Variable übergeben, in welcher die Daten gespeichert werden sollen. Dank dem Code strNick = Left(txtName & Space(50), 50) weiter oben ist sichergestellt, dass der Nick genau 50 Zeichen lang ist. Deshalb können wir aus den reingekommenen Daten die ersten 50 Zeichen abschneiden um den Nick zu erhalten. Ab Zeichen 51 ist dann die gesendete Nachricht gespeichert. Deshalb die beiden Mid-Funktionen. Mit einem Aufruf unserer Sub AddMessage wird die Nachricht ins Chat-Fenster eingefügt. Jetzt kannst du den Chat starten! Bereits können zwei Personen miteinander chatten. Allerdings ist der Chat sehr primitiv.

Verbindung schliessen  

Nach dem Motto "Einen hab' ich noch" zeige ich zum Schluss, wie die Verbindung geschlossen wird:

Private Sub cmdCancel_Click()
    If wsckChat.State <> sckClosed Then wsckChat.Close
End Sub

Erklärungen: Über die Eigenschaft State können wir den Status des Winsock-Controls abfragen. Der Wert sckClosed bedeutet soviel wie "Die Verbindung ist total geschlossen". Durch die IF-Abfrage wird also festgestellt, ob die Verbindung noch geöffnet ist. Wenn ja, dann wird sie mit dem Aufruf der Methode Close geschlossen.

Beispiel als Download  

Ich hoffe, dieser Artikel hat Dir gezeigt, wie einfach die Programmierung mit dem Winsock-Control ist. Original des Tutorials auf http://www.patrice.ch/de/computer/programming/visualbasic/tips/winsock

Beispielprojekt [8192 Bytes]

Ihre Meinung  

Falls Sie Fragen zu diesem Tutorial haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.