Sie kennen wahrscheinlich das Problem: Einfache Daten über das Winsock-Control zu versenden, ist kein Problem. Aber bei größeren Daten (ab 8 KB) und bei mehreren hintereinander versendeten Daten wird es etwas schwierig. Hier bei vb@rchiv gibt es zwar schon zwei Tipps, die diese Probleme zu beheben versuchen, allerdings funktionieren diese nicht ganz perfekt, und man kann sie nicht gemeinsam verwenden. Um das Winsock-Control mit anspruchsvollen Daten zu verwenden, müssen Sie folgendes wissen:
Eine Lösung dieses Problems erreicht man am einfachsten, indem man die Länge des zu versendenden Datenpaketes vor den eigentlichen Nutzdaten sendet. Hier haben jedoch die bereits veröffentlichten Tipps Nachteile:
Um diese Probleme zu beheben und eine universelle Winsock Sende- und Empfangsroutine zu bekommen, die einzelne Pakete als solche erkennt und auch keine Probleme mit großen Daten hat, können Sie die folgenden Prozeduren verwenden. Zum Senden von Daten verwenden Sie die Winsock1Senden-Prozedur, die die Länge der zu versendenden Daten am Anfang, gefolgt von einem Leerzeichen als Trennzeichen zu den Nutzdaten, sendet. Beim Empfangen von Daten wird die Prozedur WsockEmpfangsstatus ausgeführt, die den Übertragungsfortschritt des aktuellen Pakets in Prozent angibt. Wenn das Paket vollständig übertragen wurde, wird die Prozedur WsockStrVerarbeiten ausgelöst, mit der Sie das empfangene Paket weiter verarbeiten können. Anmerkung: Da Strings in VisualBasic im Unicode-Format im Speicher abgelegt werden (1 Zeichen wird durch 2 Bytes dargestellt), das Winsock-Control einen String jedoch im ASCII/ANSI-Format sendet (1 Zeichen = 1 Byte), sollten Sie vorsichtig beim Versenden von sehr großen Daten sein. Wenn Sie z. B. eine 50 MB große Datei versenden wollen, belegt das Empfangsprogramm während der Übertragung mindestens 100 MB an Arbeitsspeicher. Public Sub Winsock1Senden(sData As String) ' Sendet die Länge des Datenpakets und ' ein Leerzeichen zur Abgrenzung zu den Nutzdaten Winsock1.SendData CStr(Len(sData)) & " " & sData End Sub Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long) ' Fehlerbehandlung On Error GoTo WsockErr ' Schutz vor Überlappung und mehrfacher Ausführung ' (z.B. bei "DoEvents" in der Verarbeitungsprozedur) Static bAlreadyRunning As Boolean ' Andere Variablen, die benötigt werden Static sWsockZwischenspeicher As String Static sPaketZwischenspeicher As String Static nGesamtlaengePaket As Long Static nBereitsuebertragenPaket As Long If bytesTotal = 0 Then ' Die Prozedur wurde manuell aufgerufen, um nach ' einer Verbindungstrennung die Variablen zurückzusetzen sWsockZwischenspeicher = "" nGesamtlaengePaket = 0 Exit Sub End If Dim strTemp As String Dim lngTemp As Long ' Daten empfangen Winsock1.GetData strTemp ' Empfangene Daten dem Winsock-Zwischenspeicher hinzufügen sWsockZwischenspeicher = sWsockZwischenspeicher & strTemp ' Wenn Prozedur bereits ausgeführt wird, an dieser Stelle ' abbrechen und warten, bis die ursprüngliche Prozedur ' fortgesetzt wird If bAlreadyRunning Then Exit Sub bAlreadyRunning = True ' Ein schon angefangenes Paket wird fortgesetzt ' (Anm.: Dieser Teil muss zuerst kommen, da nach einer ' vollständigen Übertragung schon ein neues Paket im ' Übertragungsstrom sein kann und dieses dann auch ' ausgewertet werden muss) If nGesamtlaengePaket > 0 Then ' Empfangene Daten dem Paket-Zwischenspeicher hinzufügen Mid$(sPaketZwischenspeicher, nBereitsuebertragenPaket + 1) _ = Left$(sWsockZwischenspeicher _ , nGesamtlaengePaket - nBereitsuebertragenPaket) lngTemp = Len(Left$(sWsockZwischenspeicher, _ nGesamtlaengePaket - nBereitsuebertragenPaket)) ' Informationen über den Empfangsstatus aktualisieren nBereitsuebertragenPaket = nBereitsuebertragenPaket + lngTemp ' Die neuen Daten vom Winsock-Zwischenspeicher entfernen ' (bis auf evtl. neue eingetroffene Pakete) sWsockZwischenspeicher = Mid(sWsockZwischenspeicher, 1 + lngTemp) ' Übertragungsfortschrittsanzeige aufrufen WsockEmpfangsstatus 100 * nBereitsuebertragenPaket / nGesamtlaengePaket If nGesamtlaengePaket = nBereitsuebertragenPaket Then ' Das Paket wurde vollständig übertragen und kann ' weiterverarbeitet werden nGesamtlaengePaket = 0 WsockStrVerarbeiten sPaketZwischenspeicher End If End If ' Neues Paket empfangen Do While InStr(1, sWsockZwischenspeicher, " ") > 0 And _ nGesamtlaengePaket = 0 'wird nur ausgeführt, ' Wenn die Bytes, die die Länge und das Trennzeichen ' (zur Trennung von Länge und Nutzdaten) enthalten, ' vollständig übertragen sind (dabei kann jedoch die ' Länge der bereits übertragenen Nutzdaten auch 0 sein, ' z.B. wenn ein neues Paket am Ende eines großen Paketes ' übertragen wird); ansonsten bleiben die Daten im ' Winsock-Zwischenspeicher und es wird gewartet, bis ein ' Trennzeichen übertragen wird ' Gesamtlänge des Pakets ermitteln nGesamtlaengePaket = CLng(Left$(sWsockZwischenspeicher, _ InStr(1, sWsockZwischenspeicher, " ") - 1)) ' Ermitteln, wie viel vom Paket bereits übertragen wurde nBereitsuebertragenPaket = Len(Mid$(sWsockZwischenspeicher, _ InStr(1, sWsockZwischenspeicher, " ") + 1, nGesamtlaengePaket)) ' Paket-Zwischenspeicher-String mit der gesamten Länge des ' Pakets erstellen, damit stückweise hinzugekommene Daten ' nicht aufwendig im Speicher umstrukturiert werden müssen ' (wenn große Pakete übertragen werden (ab 1 MB), bringt dies ' einen erheblichen Geschwindigkeitsvorteil) sPaketZwischenspeicher = String$(nGesamtlaengePaket, "x") ' Den Anfang des Paketzwischenspeichers durch den empfangenen Daten ersetzen Mid(sPaketZwischenspeicher, 1) = Mid(sWsockZwischenspeicher _ , InStr(1, sWsockZwischenspeicher, Chr$(32)) + 1, nGesamtlaengePaket) ' Die neuen Daten vom Winsock-Zwischenspeicher entfernen ' (bis auf evtl. neue eingetroffene Pakete) sWsockZwischenspeicher = Mid(sWsockZwischenspeicher, _ InStr(1, sWsockZwischenspeicher, " ") + 1 + nBereitsuebertragenPaket) ' Übertragungsfortschrittsanzeige aufrufen WsockEmpfangsstatus 100 * nBereitsuebertragenPaket / nGesamtlaengePaket If nGesamtlaengePaket = nBereitsuebertragenPaket Then ' Das Paket wurde bereits vollständig übertragen und kann ' weiterverarbeitet werden nGesamtlaengePaket = 0 WsockStrVerarbeiten sPaketZwischenspeicher End If ' So lange wiederholen, bis keine neuen Pakete bzw. abgeschlossene ' Längenangaben mit Trennzeichen mehr im Winsock-Zwischenspeicher ' enthalten sind Loop bAlreadyRunning = False Exit Sub WsockErr: ' Fehler beim Verarbeiten der Daten bzw. beim Ermitteln der Länge ' des Pakets (falsches Format beim Sender?) nGesamtlaengePaket = 0 sWsockZwischenspeicher = "" bAlreadyRunning = False MsgBox "Fehler beim Empfangen der Dateien; falsches Sendeformat.", vbCritical End Sub Private Sub WsockEmpfangsstatus(Prozent As Double) ' Diese Prozedur gibt den Empfangsfortschritt ' in Prozent an... End Sub Private Sub WsockStrVerarbeiten(sData As String) ' Hier werden die empfangenen Pakete weiterverarbeitet... ... End Sub Zwei Sachen gibt es noch zu beachten. Wenn die Verbindung vom Winsock-Control getrennt und wiedergergestellt wird, müssen zwei der Variablen zurückgesetzt werden, damit die Übertragung wieder funktioniert. Da die Variablen mit Static deklariert sind und man deshalb nicht außerhalb der DataArrival-Prozedur aus sie zugreifen kann, ist es am einfachsten, dies in der DataArrival-Prozedur zu machen. Sie müssen nur bei allen Verbindungstrennungsereignissen (Winsock_Close, Winsock_Error und Winsock.Close) oder -wiederherstellungsereignissen (Winsock_Connect und Winsock_ConnectionRequest oder Winsock.Connect und Winsock.Accept) folgende Zeile hinzufügen: Winsock1_DataArrival 0
Beachten Sie außerdem, dass die Empfangsroutinen nur für ein Winsock-Control funktionieren. Wenn Sie sie mit einem Winsock-Steuerelementfeld verwenden wollen, müssen Sie die 5 mit Static deklarierten Variablen als Array dimensionieren und den Code entsprechend anpassen ("Index" an die Variablennamen anfügen). Dieser Tipp wurde bereits 15.327 mal aufgerufen.
Anzeige
![]() ![]() ![]() (einschl. Beispielprojekt!) Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv! - nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten - Symbol-Galerie mit mehr als 3.200 Icons im modernen Look Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m. |
vb@rchiv CD Vol.6 ![]() ![]() Geballtes Wissen aus mehr als 8 Jahren vb@rchiv! Online-Update-Funktion Entwickler-Vollversionen u.v.m. Tipp des Monats ![]() Dieter Otter sevTabStrip: Rechtsklick auf Reiter erkennen Eine Funktion, mit der sich prüfen lässt, auf welchen Tab-Reiter ein Mausklick erfolgte sevZIP40 Pro DLL ![]() Zippen und Unzippen wie die Profis! Mit nur wenigen Zeilen Code statten Sie Ihre Anwendungen ab sofort mit schnellen Zip- und Unzip-Funktionen aus. Hierbei lassen sich entweder einzelnen Dateien oder auch gesamte Ordner zippen bzw. entpacken. |
||||||||||||||||
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein. |