Seite 1 von 4
noch ein daten senden problem
Verfasst: 05.01.2013 18:38
von Moxl
Hallo an alle
ich hab vor strings mittels SendNetworkData() zu senden.
Jetzt sende ich ja erst die stringlänge und direkt danach den string und so rufe ich beim empfänger dann auch die daten ab...
also wenn daten zum abrufen verfügbar sind dann empfängt er erst die stringlänge und direkt danach empfängt der die daten des strings
hab das hier mal gebastelt
Code: Alles auswählen
;Server
Procedure SendDataString(ClientID, string$)
stringsize.l=Len(string$)
*mem=AllocateMemory(stringsize)
PokeS(*mem, string$)
SendNetworkData(ClientID, @stringsize, 4)
Debug "Server stringsize gesendet: "+Str(stringsize)
SendNetworkData(ClientID, *mem, stringsize)
FreeMemory(*mem)
EndProcedure
Procedure.s ReceiveDataString(ClientID)
ReceiveNetworkData(ClientID, @stringsize, 4)
Debug "Server stringsize empfangen: "+Str(stringsize)
*mem=AllocateMemory(stringsize)
ReceiveNetworkData(ClientID, *mem, stringsize)
string$=PeekS(*mem)
FreeMemory(*mem)
ProcedureReturn string$
EndProcedure
OpenConsole()
If InitNetwork()<>0
PrintN("Netzwerk initialisiert")
Else
End
EndIf
If CreateNetworkServer(0, 6800)<>0
PrintN("Server wurde gestartet")
Else
End
EndIf
PrintN("")
Repeat
Delay(20)
keypressed$=Inkey()
serverevent=NetworkServerEvent()
Select serverevent
Case #PB_NetworkEvent_Connect
PrintN("Client verbunden")
Case #PB_NetworkEvent_Data
string$=ReceiveDataString(EventClient())
PrintN(string$)
Case #PB_NetworkEvent_Disconnect
PrintN("Client nicht mehr verbunden")
EndSelect
Until keypressed$=Chr(27)
End
Code: Alles auswählen
;Client
Procedure SendDataString(ClientID, string$)
stringsize.l=Len(string$)
*mem=AllocateMemory(stringsize)
PokeS(*mem, string$)
SendNetworkData(ClientID, @stringsize, 4)
Debug "Client stringsize gesendet: "+Str(stringsize)
SendNetworkData(ClientID, *mem, stringsize)
FreeMemory(*mem)
EndProcedure
Procedure.s ReceiveDataString(ClientID)
ReceiveNetworkData(ClientID, @stringsize, 4)
Debug "Client stringsize empfangen: "+Str(stringsize)
*mem=AllocateMemory(stringsize)
ReceiveNetworkData(ClientID, *mem, stringsize)
string$=PeekS(*mem)
FreeMemory(*mem)
ProcedureReturn string$
EndProcedure
OpenConsole()
If InitNetwork()<>0
PrintN("Netzwerk initialisiert")
Else
End
EndIf
verbindung=OpenNetworkConnection("localhost", 6800)
If verbindung<>0
PrintN("Verbindung hergestellt")
Else
End
EndIf
PrintN("")
Delay(3000)
SendDataString(verbindung, "teststring")
Repeat
Delay(20)
keypressed$=Inkey()
clientevent=NetworkClientEvent(verbindung)
Select clientevent
Case #PB_NetworkEvent_Data
string$=ReceiveDataString(EventClient())
PrintN(string$)
EndSelect
Until keypressed$=Chr(27)
End
mit "localhost" funktioniert auch alles wunderbar... aber wenn ich ne ip bzw ne dyndns eingebe, dann kommt beim debugger nur müll raus :/ erst empfängt der server 1 und danach immer ne andere 10-15 stellige zahl
woran liegt das?
Re: noch ein daten senden problem
Verfasst: 05.01.2013 19:56
von Sicro
Hallo Moxl,
du berücksichtigst wie viele nicht die Rückgabewerte von SendNetworkData bzw. ReceiveNetworkData. Die Befehle müssen so gut wie immer mehrfach aufgerufen werden, um alle Daten zu senden/empfangen.
Re: noch ein daten senden problem
Verfasst: 05.01.2013 20:40
von STARGÅTE
Da ich auch keine Lust habe den Code zu korrigieren, hier nur ein paar Worte zum Verständnis:
SendNetworkData:
Die Funktion SendNetworkData() macht nichts anderes, als den übergebenen Speicherbereich in den Ausgangspuffer der Netzwerkkarte zu kopieren. Dabei werden mehre Puffer einfach hintereinander abgelegt, ohne Abgrenzung. Die eigentliche Übertragung verkläuft also nicht zwangsläuftig in den Puffergrößen, die bei SendNetworkData() angegeben sind.
Der Rückgabewert gibt keinerlei Aufschluss darüber ob, wann und wie viele Bytes tatsächlich übertragen wurden! Das einzige was u.u. zurückgegeben wird, ist ein Fehler wenn der Puffer voll ist.
ReceiveNetworkData:
Die Funktion ReceiveNetworkData() macht nichts anderes, als vorhandene Daten aus dem Netzwerk-Eingangspuffer in den übergebenen Speicher zu kopieren. Dabei wird zum Zeitpunkt des Aufrufs nur das Kopiert, was auch da ist, unabhängig davon ob die Übertragung schon fertig ist, oder noch was kommt. Dabei ist der Längenparameter nur eine Vorgabe.
Nur der Rückgabewert selbst gibt an, wie viel tatsächlich kopiert wurde.
Was ist also das Problem bei deinem Code:
SendDataString() ist erst mal soweit ok, auch wenn du nicht prüfts, ob SendNetworkData() ggf. fehlschlägt.
ReceiveDataString() ist dageben falsch. Beim zweiten ReceiveNetworkData() sollen zwar "stringsize"-Bytes gelesen werden, aber ob das wirklich der Fall war, überprüfst du nicht. Es kann durchaus sein, das die 4-Bytes für die länge bereits angekommen sind, der String selber aber noch unterwegs ist, dann würde beim 2. mal 0 zurückgegeben werden, sodass du warten musst. Da du das nicht gemacht hast, empfängt er danach immer wieder neue 4-Bytes als Länge, obwohl es vllt schon der String selbst ist. Hier müsstest du eine Schleife einbauen, die solange die restlichte Länge einließt, bis alles vom String da ist. Erst danach darfst du die Funktion verlassen.
Re: noch ein daten senden problem
Verfasst: 05.01.2013 20:44
von Moxl
ahhh eine wunderschöne beschreibung

danke
ja du hast recht.. wenn ich eine schleife bei ReceiveNetworkData mache dann funktionierts
is alles sehr gut nachvollziehbar
vielen dank

Re: noch ein daten senden problem
Verfasst: 05.01.2013 20:49
von STARGÅTE
Wäre nett, wenn du deinen korrigierten Code bitte noch mal postest, damit andere deine "Lösung" auch benutzen können, bzw. wir noch mal drüber gucken können.
Re: noch ein daten senden problem
Verfasst: 05.01.2013 21:05
von Moxl
okay also mein code sieht jetzt wie folgt aus... jetzt hab ich nur ein problem und zwar wenn ich zwei strings nach einander senden will... dann kommt beim zweiten string nich das raus was ich gesendet habe...
Code: Alles auswählen
;Server
Procedure.s ReceiveDataString(ClientID)
result=ReceiveNetworkData(ClientID, @stringsize, 4)
If result=4
*mem=AllocateMemory(stringsize)
counter=0
Repeat
counter+1
Delay(1)
result=ReceiveNetworkData(ClientID, *mem, stringsize)
Until result=stringsize Or counter>6000
If result=stringsize
string$=PeekS(*mem)
FreeMemory(*mem)
EndIf
EndIf
ProcedureReturn string$
EndProcedure
OpenConsole()
If InitNetwork()<>0
PrintN("Netzwerk initialisiert")
Else
End
EndIf
If CreateNetworkServer(0, 6800)<>0
PrintN("Server wurde gestartet")
Else
End
EndIf
PrintN("")
Repeat
Delay(20)
keypressed$=Inkey()
serverevent=NetworkServerEvent()
Select serverevent
Case #PB_NetworkEvent_Connect
PrintN("Client verbunden")
Case #PB_NetworkEvent_Data
string$=ReceiveDataString(EventClient())
PrintN(string$)
Case #PB_NetworkEvent_Disconnect
PrintN("Client nicht mehr verbunden")
EndSelect
Until keypressed$=Chr(27)
End
Code: Alles auswählen
;Client
Procedure SendDataString(ClientID, string$)
stringsize.l=Len(string$)
*mem=AllocateMemory(stringsize)
PokeS(*mem, string$)
SendNetworkData(ClientID, @stringsize, 4)
SendNetworkData(ClientID, *mem, stringsize)
FreeMemory(*mem)
EndProcedure
OpenConsole()
If InitNetwork()<>0
PrintN("Netzwerk initialisiert")
Else
End
EndIf
verbindung=OpenNetworkConnection("localhost", 6800)
If verbindung<>0
PrintN("Verbindung hergestellt")
Else
End
EndIf
PrintN("")
Delay(3000)
SendDataString(verbindung, "teststring")
SendDataString(verbindung, "teststringnummerzwei")
Repeat
Delay(20)
keypressed$=Inkey()
Until keypressed$=Chr(27)
End
Re: noch ein daten senden problem
Verfasst: 05.01.2013 22:11
von STARGÅTE
Dein Code ist ja auch noch nicht richtig.
Natürlich musst du die Memory-Position anpassen (wenn du bereits ein teil bekommen hast) und dann auch die noch zu lesende Datenmenge.
Außerdem solltest du den reservierten Speicher IMMER freigeben, und nicht nur dann, wenn es erfolg hatte.
Auch wenn ich den Code noch nicht "schön" finde, sollte er nun funktionieren:
Code: Alles auswählen
Procedure.s ReceiveDataString(ClientID)
Protected ReceivedLength.i, string$, result, counter, stringsize.l, *mem
result=ReceiveNetworkData(ClientID, @stringsize, 4)
If result=4
*mem=AllocateMemory(stringsize)
counter=0
Repeat
counter+1
Delay(1)
result=ReceiveNetworkData(ClientID, *mem+ReceivedLength, stringsize-ReceivedLength)
If result > 0
ReceivedLength + result
EndIf
Until ReceivedLength = stringsize Or counter>6000
string$ = PeekS(*mem)
FreeMemory(*mem)
EndIf
ProcedureReturn string$
EndProcedure
Re: noch ein daten senden problem
Verfasst: 05.01.2013 22:21
von Sicro
STARGÅTE hat geschrieben:SendNetworkData:
Der Rückgabewert gibt keinerlei Aufschluss darüber ob, wann und wie viele Bytes tatsächlich übertragen wurden!
Ob die Bytes tatsächlich schon übertragen wurden oder dann noch im Sendebuffer sind, weiß ich nicht, aber der Rückgabewert gibt sehr wohl die übertragene/kopierte Datenmenge zurück. Bei schlechten Verbindungen können bereits schon bei kurzen Strings (z.B. HTML-Request-Header) mehrere Aufrufe von SendNetworkData erforderlich sein.
Code: Alles auswählen
Procedure.s ReceiveDataString(ClientID)
result=ReceiveNetworkData(ClientID, @stringsize, 4)
If result=4
[...]
Und wenn result nicht 4 (Bytes) ist?
Es kann sein, dass erst 2 Bytes empfangen wurden und die anderen 2 Bytes erst noch empfangen werden müssen. Die 2 Bytes die du nun in meinem Beispiel bereits ausgelesen hast, musst du zwischenspeichern (die sind ja nun nicht mehr im Emfangspuffer) und mit den noch folgenden 2 Bytes ergänzen, um das vollständige Long dann zu erhalten:
Code: Alles auswählen
*mem = AllocateMemory(4)
If *mem = 0
Debug "Speicherbereich konnte nicht reserviert werden!"
End
EndIf
time = ElapsedMilliseconds()
Repeat
If NetworkServerEvent() = #PB_NetworkEvent_Data
time = ElapsedMilliseconds()
ReceivedDataSize = ReceiveNetworkData(EventClient(), *mem + AllReceivedDataSize, 4 - AllReceivedDataSize)
If ReceivedDataSize > 0
AllReceivedDataSize + ReceivedDataSize
EndIf
If AllReceivedDataSize = 4
; Wir haben den vollständigen Long !!!
stringsize.l = PeekL(*mem)
Break
EndIf
EndIf
If (ElapsedMilliseconds() - time) >= 10000 ; 10 Sekunden TimeOut
; Die Übertragung dauert zu lange und wird abgebrochen
Break
EndIf
ForEver
FreeMemory(*mem)
Rückgabewert von SendNetworkData wird nicht berücksichtigt.
Re: noch ein daten senden problem
Verfasst: 05.01.2013 22:39
von STARGÅTE
Sicro hat geschrieben:Ob die Bytes tatsächlich schon übertragen wurden oder dann noch im Sendebuffer sind, weiß ich nicht, aber der Rückgabewert gibt sehr wohl die übertragene/kopierte Datenmenge zurück. Bei schlechten Verbindungen können bereits schon bei kurzen Strings (z.B. HTML-Request-Header) mehrere Aufrufe von SendNetworkData erforderlich sein.
Was du mit "schlechte" Verbindungs meinst weiß ich nicht. Aber fest steht, dass SendNetworkData auf jedenfall
nicht wartet bis die Daten angekommen sind, sondern nur zurück gibt, ob das abschicken erfolgreich war.
Folgender Code gibt mir innerhalb einer Sekunde das Resultat von SendNetworkData zurück: 10485760 (alle 10MB) sind "verschickbar".
Danach kommen aber nur "kleckerweise" die Daten an (upload nur 14kB/s):
Hier benutze ich meine Internet-IP, damit die Daten wirklich verschickt werden.
Code: Alles auswählen
InitNetwork()
CreateNetworkServer(1, 7000)
CID = OpenNetworkConnection("84.189.***.***", 7000)
*Buffer = AllocateMemory(10*1024*1024)
RandomData(*Buffer, MemorySize(*Buffer))
Debug SendNetworkData(CID, *Buffer, MemorySize(*Buffer))
Repeat
If NetworkServerEvent() = #PB_NetworkEvent_Data
Debug ReceiveNetworkData(EventClient(), *Buffer, MemorySize(*Buffer))
Else
Delay(1)
EndIf
ForEver
10485760
1452
1452
1452
1452
1452
1452
1452
1452
Sicro hat geschrieben:Und wenn result nicht 4 (Bytes) ist?Es kann sein, dass erst 2 Bytes empfangen wurden und die anderen 2 Bytes erst noch empfangen werden müssen. Die 2 Bytes die du nun in meinem Beispiel bereits ausgelesen hast, musst du zwischenspeichern (die sind ja nun nicht mehr im Emfangspuffer) und mit den noch folgenden 2 Bytes ergänzen, um das vollständige Long dann zu erhalten:
Das ist natürlich richtig, danke fürs Update. Hab selbst auch noch mal in meinem Include geguckt, und dort hab ich es auch drin.
Re: noch ein daten senden problem
Verfasst: 05.01.2013 22:59
von Moxl
gut okay hab jetzt nochmal den code von stargate ausprobiert aber leider funktioniert es immernoch nich :/
das mit dem überprüfen das wirklich alle 4 byte da sind das hab ich mir jetzt mal gespart weil die eigentlich immer ankommen :/