Visual Basic Forum

Visual Basic Forum
für VB6 und VB.NET Programmierer
 
RegistrierenRegistrieren  LoginLogin

Neues Thema eröffnen   Neue Antwort erstellen    Visual Basic Forum Foren-Übersicht -> [VB6] Tutorials
Autor
Nachricht
ZiG
Überflieger
Überflieger

Anmeldedatum: 16.04.2008
Beiträge: 421

Winsock File Transfer
Verfasst am: 15.06.2009, 11:16

Thema: Winsock Datentransfer

1. Einleitung
2. Client - Dateiversand
3. Server - Dateiempfang
4. Fazit


1. Einleitung
Nach dem Tutorial über das Winsock Array möchte ich euch in diesem Tutorial noch zeigen wie einfach es ist eine Datei per Winsock zu versenden.
Viele sources die verbreitet werden sind entweder schwer zu verstehen oder nutzen die Technik jedes Byte einzeln zu versenden, was natürlich enorme Zeit braucht bei größeren Dateien.
Ich werde euch eine viel einfachere Technik an einem simplen Beispiel zeigen, die ich benutze.

Benötigen werdet ihr:
Beim Client:
1. 1x Common Dialog Control (Im Code als „cdlg“ abgekürzt)
2. 1x Button (Command1)
3. 1x Winsock Control (ws)
4. 1x Label (Label1)
Beim Server:
1. 1x Button (Command1)
2. 2x Label (Label1 und Label2)
3. 1x Winsock Control (ws)

2. Client - Dateiversand
Den Client werden wir so coden, dass er für den Dateiversand zuständig ist.
Damit wir überhaupt mal Verbindungen entgegen nehmen können müssen wir das Winsock Control auf Listen setzen.
Code:
Private Sub Form_Load()<br />ws.LocalPort = 2222<br />ws.Listen<br />End Sub
Und eingehende Verbindungen akzeptieren wir hiermit.
Code:
Private Sub ws_ConnectionRequest(ByVal requestID As Long)<br />ws.Close<br />ws.Accept requestID<br />Label1.Caption = "Connection established"<br />End Sub
Damit wir auch sehen ob eine Verbindung besteht, wird gleich in Label1 eine Message ausgegeben.
Das selbe wenn eine Verbindung geschlossen wird.
Code:
Private Sub ws_Close()<br />Label1.Caption = "Connection lost"<br />End Sub
Das waren jetzt mal so die Standard Sachen für eine simple Winsock Verbindung.
Jetzt benutzen wir noch das Common Dialog Control im Button, damit ihr später einfach eine Datei aussuchen könnt.
Code:
Private Sub Command1_Click()<br />On Error GoTo Err:<br /><br />With cdlg<br /> .CancelError = True<br /> .ShowOpen<br /> If SendFile(.FileName) Then GoTo Err:<br />End With<br /><br />Exit Sub<br />Err:<br />Call MsgBox("Error while sending the file!", vbCritical)<br />End Sub
Bis jetzt sollte eigentlich alles ohne Erklärungen klar sein. Ansonsten solltet ihr euch vorher andere Tuts ansehen, die euch mehr Basiswissen übers Winsock vermitteln.

Und jetzt kommen wir zum eigentlichen code. Jetzt kümmern wir uns um die Funktion Sendfile, die in Command1 aufgerufen wird.

Code:
Private Function SendFile(ByVal Filepath As String) As Boolean<br />'Hier wird die Datei versendet<br />Dim buffer As String, pos As Long, bytes As Long, AllComplete As Boolean<br /><br />pos = 1<br />bytes = 65535<br />AllComplete = False<br />SendComplete = False<br /><br />'Datei öffnen<br />Open Filepath For Binary As #1<br /><br />'Die Schleife läuft so lange, bis die Datei versendet wurde<br />Do<br /> If (LOF(1) - pos) > bytes Then<br />  'Teil der Datei einlesen<br />  buffer = Space(bytes)<br />  Get #1, pos, buffer<br />  pos = pos + bytes<br /> Else<br />  bytes = (LOF(1) - pos) + 1<br />  buffer = Space(bytes)<br />  Get #1, pos, buffer<br />  AllComplete = True<br /> End If<br /> <br /> 'Daten senden<br /> ws.SendData (buffer)<br /> buffer = ""<br /> <br /> 'Warten bis der Teil gesendet wurde<br /> Do<br />  DoEvents<br /> Loop Until SendComplete<br />Loop Until AllComplete<br /><br />Close<br />Call MsgBox("Sending complete")<br /><br />End Function
Erklärung zur Funktion
Im Grunde ist es sehr einfach.
Der Code funktioniert so, dass er die Datei Stückchenweise einliest und versendet.
Da das Winsock Control immer nur eine gewisse Menge an Bytes auf einmal versenden kann (65535Bytes max), können wir auch nicht größere Stücke auslesen.

Hier mal die wichtigsten Variablen:
pos zeigt immer unsere letze Position in der Datei an. Mit 1 fangen wir natürlich an.
bytes übergibt die Anzahl an Bytes, die immer ausgelesen werden sollen.
AllComplete ist True, wenn die komplette Datei versendet wurde.
SendComplete ist True, wenn ein Teil der Datei versendet wurde.
Filepath ist natürlich der Pfad zur Datei, die gesendet werden soll.
buffer ist der Zwischenspeicher für unsere Teile der Datei.

Und jetzt erkläre ich noch die wichtigen Zeilen.
Code:
If (LOF(1) - pos) > bytes Then
Diese If Abfrage überprüft ob die noch zu auslesenden Bytes mehr sind, als in bytes drinnen steht.
Wozu? Ganz einfach.
Wir wollen immer 65535Bytes auslesen. Wenn wir aber ans Ende der Datei kommen und nur noch z.B. 821Bytes zum auslesen sind, würden wir beim einlesen aus der Datei Blödsinn erhalten oder sogar einen Fehler.
Und wenn also weniger als 65535Bytes übrig sind zum auslesen, dann wird die Anzahl der restlichen Bytes an die Variable bytes übergeben.
Code:
bytes = (LOF(1) - pos) + 1
Und hier die Erklärung zum einlesen der Datei:
Code:
  buffer = Space(bytes)<br />  Get #1, pos, buffer<br />  pos = pos + bytes
Wir benutzen eine string Variable und nicht eine byte, so wie in vielen anderen sources.
Mit Get können wir unseren Teil einlesen. Aber man kann nur sagen, von wo er zum einlesen anfangen soll. Natürlich von pos.
Aber man kann nicht angeben, wie viel er einlesen soll.
Deshalb füllen wir die Variable buffer vorher mit sovielen Leerzeichen wie in bytes drinnen steht.
Stellt euch den string am besten wie eine leere Flasche vor, die sich bis zum Rand füllt wenn ihr sie unters Wasser haltet. Mehr passt einfach nicht rein.
Wenn wir also buffer mit genau 65535 Leerzeichen füllen, passt auch nicht mehr hinein.

Und in der Zeile „pos = pos + bytes“ wird einfach die letze Position aktualisiert, damit wir beim einlesen des nächsten Teiles wissen wo wir zuletzt waren.

Und jetzt kommt noch etwas sehr wichtiges.
Code:
Do<br />  DoEvents<br /> Loop Until SendComplete
Ich weiß. Sieht nicht wichtig aus, ist es aber.
Diese Schleife läuft solange, bis die Boolean Variable SendComplete True ist.
Diese Variable müsst ihr Global deklarieren.
Und dann müssen wir sie noch in die Sub ws_SendComplete() einfügen.
Code:
Private Sub ws_SendComplete()<br />SendComplete = True<br />End Sub
Wenn ein Teil versendet wurde, wird diese Sub ausgelöst und unsere Variable auf True gesetzt.
Und das war es auch schon mit dem Klienten.


3. Server - Dateiempfang

Hier mal die Grundlegenden Sachen.
Code:
Private Sub Command1_Click()<br />ws.Connect "127.0.0.1", 2222<br />End Sub<br /><br />Private Sub ws_Close()<br />Label1.Caption = "Connection lost"<br />End Sub<br /><br />Private Sub ws_Connect()<br />Label1.Caption = "Connection established"<br />End Sub
Und hier die Sub zum empfangen der Datei.
Code:
Private Sub ws_DataArrival(ByVal bytesTotal As Long)<br />Dim buffer As String<br /><br />ws.GetData buffer<br />Open (App.Path & "test.exe") For Binary As #1<br />Put #1, LOF(1) + 1, buffer<br />buffer = ""<br />Close<br /><br />End Sub
In buffer empfangen wir die einzelnen Teile.
Und mit Put #1, LOF(1) +1, buffer schreiben wir jeden Teil ans Ende der Datei.
Zur Sicherheit leeren wir dann noch die Variable buffer

4. Fazit
Wie ihr seht ist es also gar nicht so schwer. Wink
Natürlich ist das Beispiel sehr simple. Aber ich hoffe, dass ich euch ein wenig die Funktionsweise eines Datentransfers vermitteln konnte.

Hier habe ich auch noch den Beispielsource als Download für euch.
Download: Link
pw: vb-x.org

mfg, ZiG
_________________
 
Neues Thema eröffnen   Neue Antwort erstellen    Visual Basic Forum Foren-Übersicht -> [VB6] Tutorials

Tags: winsock, file, datei, download

 
 Verwandte Themen   Aufrufe   Letzter Beitrag 
Keine neuen Beiträge Visual Basic Download ? 1741 03.05.2011, 07:38
Keine neuen Beiträge Api Download in Prozent + Kb anzeige + Progrezzbar 1344 21.10.2007, 13:03
Keine neuen Beiträge Download 1358 30.08.2007, 15:45
Keine neuen Beiträge Download mit Internet Explorer Object 923 18.08.2008, 19:00
Keine neuen Beiträge Visual Basic 6 download 3694 26.05.2007, 11:51
 



[ Time: 0.1718s ][ Queries: 83 (0.0551s) ][ GZIP on - Debug on ]