# Winsock File Transfer



## Benedikt (10. Oktober 2002)

Hi!
Mein Ziel ist ein Programm (2 um genauer zu sein), mit welchem ich Dateien über das Internet versenden kann (direkte TCP/IP Verbindung)
ALso....
Das hab ich schonmal gecodet:
Client:
-------
Private Sub Command1_Click()
ws.Connect txtIP.Text, 33333
End Sub

Private Sub Command2_Click()
Open "C:\prog.exe" For Binary Access Read As #1
Do Until EOF(1)
Dim x(0 To 512) As Byte
Get #1, , x
ws.SendData x
Loop
Close #1
End Sub

Private Sub ws_DataArrival(ByVal bytesTotal As Long)
Dim daten As String
ws.GetData daten
End Sub

und der Server:
----------------

Private Sub Form_Load()
ws.LocalPort = 33333
ws.Close
ws.Listen
End Sub

Private Sub ws_ConnectionRequest(ByVal requestID As Long)
If ws.State <> sckClosed Then ws.Close
ws.Accept requestID
End Sub


Private Sub ws_DataArrival(ByVal bytesTotal As Long)
Open "prog.exe" For Binary Access Write As #1
Dim x(0 To 512) As Byte
Put #1, , x
ws.GetData x
Loop
Close #1
End Sub


Also ich versteh wirklich nicht, wieso dass nicht funktioniert
Vielen Dank 
Benedikt


----------



## Dario Linsky (10. Oktober 2002)

das kann auch gar nicht funktionieren, weil du im onDataArrival-ereignis auf dem server die datei immer wieder überschreibst. und ausserdem sollte das "loop" da weg. 

probier mal folgenden code:

```
Option Explicit

Dim datei() As Byte
Private pos As Long

Private Sub Command1_Click()
On Error GoTo 2

wsClient.Connect "127.0.0.1", 33333

Exit Sub
2   MsgBox "Fehler 2: " & Err.Description

End Sub

Private Sub Form_Load()
On Error GoTo 1

wsServer.LocalPort = 33333
wsServer.Close
wsServer.Listen

Exit Sub
1   MsgBox "Fehler 1: " & Err.Description

End Sub

Private Sub wsClient_Connect()
On Error GoTo 5

Dim b As Byte

'Datei puffern
Open "D:\test.doc" For Binary Access Read As #1
Do While Not EOF(1)
    Get #1, , b
    wsClient.SendData b
    DoEvents
Loop
Close #1

Exit Sub
5   If Err.Number <> 40006 Then
        MsgBox "Fehler 5: " & Err.Description
    Else
        MsgBox "Fehler 5: Verbindung vorzeitig unterbrochen"
        End
    End If
End Sub

Private Sub wsClient_DataArrival(ByVal bytesTotal As Long)
On Error GoTo 3

Dim daten As String
wsClient.GetData daten

Exit Sub
3   MsgBox "Fehler 3: " & Err.Description

End Sub

Private Sub wsServer_ConnectionRequest(ByVal requestID As Long)
On Error GoTo 4

If wsServer.State <> sckClosed Then
    wsServer.Close
End If
wsServer.Accept requestID

Exit Sub
4   MsgBox "Fehler 4: " & Err.Description

End Sub

Private Sub wsServer_DataArrival(ByVal bytesTotal As Long)
On Error GoTo 6

Dim b As Byte

wsServer.GetData b

pos = pos + 1

Open "D:\test2.doc" For Binary Access Write As #2
Seek #2, pos
Put #2, , b
Close #2

Exit Sub
6   MsgBox "Fehler 6: " & Err.Description

End Sub
```
ich hab das ganze nur lokal laufen lassen, aber wenn man die ip-adresse austauscht, klappt das auch im internet. das problem dabei ist aber noch, dass von der datei jedes byte einzeln übertragen wird, und dadurch dauert das ziemlich lange.
das kann man aber lösen, indem man beim einlesen der datei immer eine bestimmte menge von bytes (z.b. 4096 = 4kb) zu paketen zusammenfasst und gleichzeitig verschickt. du liest immer 4096 bytes ein, verschickst diese und liest die nächsten 4096 bytes ein, verschickst die wieder, und so weiter...
dabei musst du darauf achten, dass sich nicht jede datei in blöcke mit jeweils 4096 bytes aufteilen lässt - also musst du den letzten block immer etwas kleiner machen!
und wenn du beim empfangen der daten auf dem server sofort eine datei schreibst, musst du mit seek zuerst ans ende der datei springen, sonst überschreibst du die bisherigen daten. oder du pufferst beim empfangen der daten zuerst alle bytes in einem array und schreibst nachher erst die datei.


----------



## Benedikt (17. Oktober 2002)

VIELEN DANK!!!
Danke, asphyxia!
Du hast mir wirklich sehr geholfen.
Dein code funktioniert sehr gut.
Was aber nicht schlecht wäre, ist eine
Statusbar, die anzeigt, wieviel schon gesendet
wurde.
Benedikt


----------



## Dario Linsky (18. Oktober 2002)

in einer statusbar könntest du die bisher gesendeten daten anzeigen. also z.b. 59% von 1234kb oder so ähnlich. das kannst du in deiner schleife mit einbauen. allerdings wird das vermutlich etwas flackern, weil das fenster mehrmals pro sekunde neu gezeichnet wird. 

die andere alternative wäre eine progressbar. dabei legst du den maximalen wert auf die gesamtgrösse der datei und bei jedem schleifendurchlauf addierst du die anzahl der gesendeten bytes zum aktuellen wert.
die progressbar kann man mit ein paar api-funktionen auch in einer statusbar unterbringen.


----------



## Benedikt (18. Oktober 2002)

*re*

ja...
Das mit der statusbar hab ich gestern mal versucht.
Ich habe es folgendermassen gemacht:
(im server)
status.value = ws.BytesRecived :-( 
Also das problem ist, dass ich die Grösse der Datei ermitteln muss, damit ich die länge der statusbar festlegen kann (angenommen die Datei ist 1000 Kb gross, dann ist die statusbar.max = 1000,
verstehst du was ich meine? Kannst du mir vileicht einen Typ geben, wie ich die Dateigrösse ermitteln kann?


----------



## Dario Linsky (18. Oktober 2002)

die dateigrösse kannst du nur lokal auslesen. das heisst, der client müsste zuerst die dateigrösse auslesen, diese an den server schicken und dann erst mit dem eigentlichen dateitransfer anfangen.
an die dateigrösse kommst du mit einem filesystemobject.


----------



## e-axe (7. Juli 2003)

dateigroesse in byte: FileLen("c:\testfile.exe")

mfg ich


----------



## daredevil (14. Juli 2003)

Hallo,
ich bin neu hier und will das gleiche Programm wie Bendedikt schreiben, aber ich krieg keinen Durchblick durch den Code von Lirion. Kann mir den jemand nochmal geben, dass auch ich kapier, was zum Server und was zum Client gehört und wie das ganze mit der progressbar funktioniert.

Ich wär euch sehr sehr dankbar...

daredevil


----------



## Dario Linsky (15. Juli 2003)

Was daran verstehst Du nicht? Das gehört alles in ein einziges Formular - sprich: Du kannst den ganzen Code einfach kopieren und musst nur noch darauf achten, dass die Objekte und Steuerelemente die richtigen Namen haben.
Zur Progressbar:


> dabei legst du den maximalen wert auf die gesamtgrösse der datei und bei jedem schleifendurchlauf addierst du die anzahl der gesendeten bytes zum aktuellen wert.


----------



## Twips (16. August 2003)

*Fehler*

Hallo
Ich mache ein Dateiübertragungs-Programm und habe den Code mal ausprobiert.
Leider stürzt Visual Basic beim Beenden des Programms immer ab.
Hat da jemand ne ahnung, warum ?!

Ich hab probiert, dass ganze mal etwas kleiner zu machen, nur mit dem Connect befehl:

Private Sub Command2_Click()
End
End Sub
Private Sub Verbinden_Click()
wsClient.RemoteHost = txtIP.Text
wsClient.RemotePort = Port.Text
wsClient.Connect
End Sub

Aber so gar da stürzt Visual Basic ab.
Hab keine Ahnung was sich VB dabei gedacht hat.


----------



## Daniel Toplak (16. August 2003)

> oder du pufferst beim empfangen der daten zuerst alle bytes in einem array und schreibst nachher erst die datei.


@ Lirion:
Das ist keine so gute Idee, stell dir mal vor du willst sagen wir mal 200 oder 500 MB verschicken, da würde sich der Arbeitsspeicher und der Auslagerungsspeicher freuen.
Es sei denn, du wirst von Infineon gesponsort 
Dann lieber doch blockweise.

Gruss Homer


----------



## Twips (17. August 2003)

Ja klar, aber es geht darum, dass VB beim Beenden des Programms abstürzt.
Auch wenn ich den Code von Benedikt nehme.


----------

