Tcp größere Datenmenge senden

  • Ich hab ein Problem mit TCP. Ich habe folgendes geschrieben,

    Spoiler anzeigen


    Global $IP = @IPAddress3

    TCPStartup()

    $Befehl = InputBox("Befehl", "Nachricht: 1;Nachricht" & @LF & "Datei Starten: 2;Dateiname"& @LF & "Datei senden: 3;jetziger Dateiname;späterer Dateiname")
    if $Befehl = 3 Then
    $teil = StringSplit($Befehl, ';', 1)
    $Read = FileRead($teil[2])
    Local $bin = StringToBinary($Read)
    ConsoleWrite($bin & @LF)
    $Befehl = "3;" & $teil[3] & ";"& $bin
    EndIf

    MsgBox(0, "Sender", $Befehl)

    $Socket = TCPListen($IP, 65432)

    Do
    $Connection = TCPAccept($Socket)
    Until $Connection <> -1

    TCPSend($Connection, $Befehl)
    TCPShutdown()

    Spoiler anzeigen


    TCPStartup()
    $IP = "127.0.0.1"

    $Connection = TCPConnect($IP, 65432)
    If $Connection < 0 Then
    MsgBox(16, "Error", "Konnte keine Verbindung herstellen!")
    _Exit()
    EndIf
    $Recv = TCPRecv($Connection, 1000000)
    sleep(1000)
    $teil = StringSplit($Recv, ';')
    Switch $teil[1]
    Case 1
    $msg = $teil[2]
    Case 2
    $msg = "Datei starten"
    ShellExecute($teil[2], @ScriptDir, "open")
    Case 3
    $msg = "Daten Emfangen"
    ConsoleWrite(BinaryToString($teil[3]) & @LF)
    $q = BinaryToString($teil[3])
    FileWrite($teil[2], $q)
    Case Else
    $msg = "Error"
    EndSwitch

    MsgBox(0, "Emfänger", $msg)

    Func _Exit()
    TCPShutdown()
    Exit
    EndFunc

    aber es funktioniert nur manchmal. wenn ich größere Dateien sende, wie compillierte scripte, dann kommt nur ein kleiner teil an.
    Ich hoffe, ihr könnt mir sagen, woran das liegt, und mir eine Lösung geben.

    5 Mal editiert, zuletzt von jjj (23. Juni 2013 um 20:09)

  • Versuch mal die Byte Zahl zu erhöhen:

    [autoit]

    $Recv = TCPRecv($Connection, 1000000)

    [/autoit]


    Wenn deine Datei 1 MB groß ist, müssen mindestens 1048576 Byte übertragen werden,
    denn 1 MB hat 1024 KB, und 1 KB hat 1024 Byte.

    Ich kenn mich nicht gut mit TCP aus aber versuch die Maximale Datenmenge zu erhöhen oder ersätz mal das mit folgendes im 2. Script:

    [autoit]

    $Recv = ""
    While 1 ; ließt die Datenmege solange ein bis alles angekommen ist.
    $Recv &= TCPRecv($Connection, 1024)
    If @error Then ExitLoop
    WEnd

    [/autoit]


    Das ist nur theorie und ungetestet aber ich denke das müsste funktionieren.

    Sind TV-Quizfragen zu einfach? A) Ja B) Harry Potter

    Spoiler anzeigen

    Ich gebe zu dieser Post hat wahrscheinlich nicht viel geholfen,
    aber ich versuche wenigstens zu helfen :rolleyes:

  • Ich hab den zweiten Vorschlag mal getestet, und 2 mal die gleiche .exe versendet, aber das komische ist: einmal sind 80 Zeilen und einmal 38 Zeilen von insgesamt 10455 Zeilen angekommen. ich habs noch ein par mal öfter ausprobiert und es kommen immer zwischen 20 und 1200 Zeilen an.

    2 Mal editiert, zuletzt von jjj (23. Juni 2013 um 11:47)

  • [autoit]

    $Recv = TCPRecv($Connection, 1000000)
    sleep(1000)

    [/autoit]

    wo hast du denn DAS her (das mit dem Sleep meine ich! )
    Überleg dir mal, was das Script in diesen beiden Zeilen macht, und du hast sofort die Lösung...

    btw sieht man deutlich, dass du weder eins der TCP-Beispiele in der Hilfe beachtet hast, noch irgendein funktionierendes TCP-Script!

  • keine Ahnung (schaden tust jedenfalls nicht)! Ich habs jetzt raus genommen, aber es ändert nichts.
    Es kommen immer noch nur ca. 3000 Zeilen an, und nicht 10000.

    Einmal editiert, zuletzt von jjj (23. Juni 2013 um 14:07)

  • Außerdem wäre es - meiner persönlichen Meinung nach - schöner die Datei in beispielsweise 2kb 'Häppchen' zu verschicken. Sonst ist es während der Dateiübertragung nicht mehr möglich andere Pakete auszutauschen...

    LG
    Christoph :)

  • Spoiler anzeigen
    [autoit]

    TCPStartup()
    $IP = "127.0.0.1"

    [/autoit] [autoit][/autoit] [autoit]

    $Connection = TCPConnect($IP, 65432)
    If $Connection < 0 Then
    MsgBox(16, "Error", "Konnte keine Verbindung herstellen!")
    _Exit()
    EndIf

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    While Sleep(10) ;wartet drauf bis etwas gesendet wird.
    $recv = TCPRecv($Connection, 1024*1024); 1 MB
    ;~ If @error Then ExitLoop
    If $recv <> "" Then ExitLoop
    WEnd

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;---- Dein Script ----
    Sleep(1000)
    $teil = StringSplit($Recv, ';')
    Switch $teil[1]
    Case 1
    $msg = $teil[2]
    Case 2
    $msg = "Datei starten"
    ShellExecute($teil[2], @ScriptDir, "open")
    Case 3
    $msg = "Daten Emfangen"
    ConsoleWrite(BinaryToString($teil[3]) & @LF)
    $q = BinaryToString($teil[3])
    FileWrite($teil[2], $q)
    Case Else
    $msg = "Error"
    EndSwitch

    [/autoit] [autoit][/autoit] [autoit]

    MsgBox(0, "Emfänger", $msg)

    [/autoit] [autoit][/autoit] [autoit]

    Func _Exit()
    TCPShutdown()
    Exit
    EndFunc ;==>_Exit

    [/autoit]

    So wartet das Script bis etwas empfangen wird.

    Aber such mal hier im Forum du findest hier 1000 die das gleiche Problem hatten.

    Sind TV-Quizfragen zu einfach? A) Ja B) Harry Potter

    Spoiler anzeigen

    Ich gebe zu dieser Post hat wahrscheinlich nicht viel geholfen,
    aber ich versuche wenigstens zu helfen :rolleyes:

    Einmal editiert, zuletzt von PuReIroNie (23. Juni 2013 um 16:27)

  • wie kommst du auf

    Zitat

    While Sleep(10) ;wartet drauf bis etwas gesendet wird.


    ich hab nichts dazu gefunden, könntest du mir mal den Link dazu schicken?
    Und jetzt passiert gar nichts mehr, an der stelle, an der das Script warten sollte, bis alles angekommen ist, wartet der jetzt wirklich sehr lange, ohne das etwas passiert.

    2 Mal editiert, zuletzt von jjj (23. Juni 2013 um 15:12)

  • Statt dem Sleep(10) kannste auch ne 1 oder True hinschreiben. Das schreibt man eigentlich wenn nix in der Schleife drin ist, damit deine CPU keine 100% hat. Aber bei dir ist ja was drin. Und schau mal bei $ConnectedSocket, deine Variable heißt anders ;)

  • Statt dem Sleep(10) kannste auch ne 1 oder True hinschreiben. Das schreibt man eigentlich wenn nix in der Schleife drin ist, damit deine CPU keine 100% hat. Aber bei dir ist ja was drin. Und schau mal bei $ConnectedSocket, deine Variable heißt anders ;)

    Das Sleep brauch man nicht beachten das ist so ein ding von mir ;D
    das mach ich in fast jeder schleife, aber diese Schleife kann man das Sleep auch weglassen, das stimmt ;S

    Die Variable änder ich mal ;D

    Sind TV-Quizfragen zu einfach? A) Ja B) Harry Potter

    Spoiler anzeigen

    Ich gebe zu dieser Post hat wahrscheinlich nicht viel geholfen,
    aber ich versuche wenigstens zu helfen :rolleyes:

  • das sleep

    [autoit]

    $Recv = TCPRecv($Connection, 1000000)
    sleep(1000)

    [/autoit]

    macht HINTER dem TCPRecv definitiv keinen Sinn, denn dann sind die Daten im Puffer ja schon gelesen...

    Und wer die Hilfe liest, der bemerkt, dass bei dem Parameter Maxlen steht: "Maximale Anzahl der zu erhaltenen Zeichen."
    Dort steht nirgendwo, dass darauf egwartet wird, bis zig-tausend Bytes übertragen wurden.
    Ganz im Gegenteil, der Puffer wird bis zu einem bestimmten Bereich mit Paketen gefüllt, und dann wartet TCP darauf, dass der Puffer geleert wird!
    Solange der Puffer nicht geleert wird, passiert....NICHTS! Keine weitere Übertragung!

    Daher macht man den Puffer KLEIN (1-2 Kilobytes) und holt die Daten daraus schnellstmöglich ab, damit TCP neue anfordern kann.

    [autoit]

    While Sleep(10) ;wartet drauf bis etwas gesendet wird.
    $recv = TCPRecv($Connection, 1024*1024); 1 MB
    ;~ If @error Then ExitLoop
    If $recv <> "" Then ExitLoop
    WEnd

    [/autoit]

    bringt aus genau diesem Grund NICHTS, da nur 1x Daten aus dem Puffer gelesen werden

    So sollte es sein:

    [autoit]

    $recv=""
    While Sleep(10) ;wartet drauf bis etwas gesendet wird.
    $rec= TCPRecv($Connection, 1024); $recv mit 1 KB-Paketen füllen...

    [/autoit][autoit][/autoit][autoit]

    ;~ If @error Then ExitLoop
    If $rec = "" Then ExitLoop ;....bis keine mehr kommen

    [/autoit][autoit][/autoit][autoit]

    $recv&=$rec ;alle Pakete aneinanderhängen
    WEnd

    [/autoit]


    Ich würde sowieso zuerst die Dateigröße und den Dateinamen schicken, dann weiss man wenigstens, ob alle Daten angekommen sind und wie die Datei heisst!

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    Einmal editiert, zuletzt von Andy (23. Juni 2013 um 17:24)

  • Ich würde sowieso zuerst die Dateigröße und den Dateinamen schicken, dann weiss man wenigstens, ob alle Daten angekommen sind und wie die Datei heisst!


    Deswegen machen das auch so die Hersteller von Steuerungen bei Kommunikationssachen. Am Anfang kommt die Größe der Nutzdaten. Also man sollte sich schon ein vernünftiges Protokoll überlegen und evtl. z.B. mit Base64 ein wenig komprimieren.

  • Spoiler anzeigen

    Global $IP = @IPAddress3

    TCPStartup()

    $Befehl = InputBox("Befehl", "Nachricht: 1;Nachricht" & @LF & "Datei Starten: 2;Dateiname"& @LF & "Datei senden: 3;jetziger Dateiname;späterer Dateiname")
    if $Befehl = 3 Then
    $teil = StringSplit($Befehl, ';', 1)
    $Read = FileRead($teil[2])
    $bin = StringToBinary($Read)
    $Befehl = "3;" & $teil[3] & ";"& $bin
    EndIf
    MsgBox(0, "Sender", $Befehl)

    $Socket = TCPListen($IP, 65432)

    Do
    $Connection = TCPAccept($Socket)
    Until $Connection <> -1

    TCPSend($Connection, $Befehl)
    TCPShutdown()

    Spoiler anzeigen

    TCPStartup()
    $IP = "127.0.0.1"

    $Connection = TCPConnect($IP, 65432)
    If $Connection < 0 Then
    MsgBox(16, "Error", "Konnte keine Verbindung herstellen!")
    _Exit()
    EndIf
    $Recv=""
    While Sleep(10) ;wartet drauf bis etwas gesendet wird.
    $rec= TCPRecv($Connection, 1024); $recv mit 1 KB-Paketen füllen...

    ;~ If @error Then ExitLoop
    If $rec = "" Then ExitLoop ;....bis keine mehr kommen

    $Recv&=$rec ;alle Pakete aneinanderhängen
    WEnd
    MsgBox(0, "", "Fertig")
    $teil = StringSplit($Recv, ';')
    Switch $teil[1]
    Case 1
    $msg = $teil[2]
    Case 2
    $msg = "Datei starten"
    ShellExecute($teil[2], @ScriptDir, "open")
    Case 3
    $msg = "Daten Emfangen"
    ConsoleWrite(BinaryToString($teil[3]) & @LF)
    $q = BinaryToString($teil[3])
    FileWrite($teil[2], $q)
    Case Else
    $msg = "Error"
    EndSwitch

    MsgBox(0, "Emfänger", $msg)

    Func _Exit()
    TCPShutdown()
    Exit
    EndFunc


    meistens kommt gar nichts an. (die letzten 10 mal ausprobieren)

    Einmal editiert, zuletzt von jjj (23. Juni 2013 um 19:16)

  • Hallo,
    dein Problem ist weniger das empfangen als mehr das Senden, TCP sendet nur so viel wie gerade maximal möglich ist
    gibst du TCP aber zum senden als geht wird einiges verloren gehen
    so mache ich das senden meist immer, $sReadData enthält deine Daten

    [autoit]

    While BinaryLen($sReadData)
    $i = TCPSend($Connection, $sReadData)
    $sReadData = BinaryMid($sReadData, $i + 1, BinaryLen($sReadData) - $i)
    WEnd

    [/autoit]


    und beim empfangen kannst du ruhig mehr auf einmal empfangen
    das regel ich meisten so

    [autoit]

    Local $sRecvMsg, $sRecvMsgPart
    While Sleep(40)
    $sRecvMsg = TCPRecv($Connection, 256000)
    If $sRecvMsg <> "" Then
    Do
    $sRecvMsgPart = TCPRecv($Connection, 256000)
    $sRecvMsg &= $sRecvMsgPart
    Until $sRecvMsgPart <> ""
    ; verarbeitung der Daten in $sRecvMsg
    EndIf
    WEnd

    [/autoit]


    man sollte aber immer vom worst-case scenario ausgehen und noch nen timeout einbauen mit TimerInit usw.
    schwieriger wird es wenn du mehrere Antworten vom clienten erwarten würdest, dann solltest du wirklich sowas wie ein internes protokoll entwickeln ;)

    mfg Krabat

  • Ich habs jetzt geschafft.

    Sender:

    Spoiler anzeigen

    Global $IP = @IPAddress3

    TCPStartup()

    $Befehl = InputBox("Befehl", "Nachricht: 1;Nachricht" & @LF & "Datei Starten: 2;Dateiname"& @LF & "Datei senden: 3;jetziger Dateiname;späterer Dateiname")
    if $Befehl = 3 Then
    $teil = StringSplit($Befehl, ';', 1)
    $Read = FileRead($teil[2])
    $bin = StringToBinary($Read)
    $Befehl = "3;" & $teil[3] & ";"& $bin
    EndIf

    MsgBox(0, "Sender", $Befehl)
    $Socket = TCPListen($IP, 65432)

    Do
    $Connection = TCPAccept($Socket)
    Until $Connection <> -1

    While 1
    $r = StringLeft($Befehl, 1024)
    $Befehl = StringTrimLeft($Befehl, 1024)
    TCPSend($Connection, $r)
    if $Befehl = "" then exitloop
    WEnd
    TCPShutdown()

    Empfänger:

    Spoiler anzeigen

    TCPStartup()
    $IP = "127.0.0.1"

    $Connection = TCPConnect($IP, 65432)
    If $Connection < 0 Then
    MsgBox(16, "Error", "Konnte keine Verbindung herstellen!")
    _Exit()
    EndIf

    $Befehl = ""
    While 1
    $Befehl &= TCPRecv($Connection, 1024)
    if @error then exitloop
    WEnd

    MsgBox(0, "", "Fertig")
    $teil = StringSplit($Befehl, ';')
    Switch $teil[1]
    Case 1
    $msg = $teil[2]
    Case 2
    $msg = "Datei starten"
    ShellExecute($teil[2], @ScriptDir, "open")
    Case 3
    $msg = "Daten Emfangen"
    ConsoleWrite(BinaryToString($teil[3]) & @LF)
    $q = BinaryToString($teil[3])
    FileWrite($teil[2], $q)
    Case Else
    $msg = "Error"
    EndSwitch

    MsgBox(0, "Emfänger", $msg)

    Func _Exit()
    TCPShutdown()
    Exit
    EndFunc

    Danke an alle. :)

  • so geht es zwar aber nicht optimal^^
    dein Sendescript war bereits ok so
    so wie du es jetzt hast, hast du nen upload von 1kb pro schleifendurchlauf also ne selbst eingebaute drossel
    wenn du den teil also zurück änderst hast du vollen zur verfügung stehenden upload das ist gut für große dateien ;)

    nur beim Empfangen wo ich "; verarbeitung der Daten in $sRecvMsg" schrieb hättest du ein ExitLoop einbauen müssen, damit er die schleifen verlässt
    so hing er halt für immer in der schleife und es konnte nix mehr passieren
    aber so wie du den empfänger jetzt hast kannst du den empfänger auch lassen der tut es auch, wobei ich die 1024 byte beim empfang erhöhen wurde von deinen jetzigen 1kb würde ich locker auf 100kb erhöhen zum beschleunigen

    ich hab mir schonmal überlegt ein ausführliches TCP tutorial zu machen weil die bisherigen so unvollständig sind, naja vllt. hab ich in den Sommerferien ja mal langeweile^^

    mfg ;)