Seite 1 von 1
Wie Dateinanmen bei Datenübermittlung syncronisieren?
Verfasst: 02.11.2010 11:58
von Syntacks_Error
Ein paar Clients sollen kleine Dateien (typischerweise höchstens 1 KB) mit unterschiedlichen Dateiendungen an einen Server schicken, wobei die Dateiendungen die weitere Verarbeitung auf dem Server steuern. Die Dateinamen sind immer 36 Byte lang.
Ich verwende dafür SendNetworkFile(), und weil man den Dateinamen ja nicht mitschicken kann, verschicke ich den vorweg mit SendNetworkString(). Die Serverseite sieht zum Empfang vereinfacht so aus (Wie kriegt man eigentlich das Einrücken hin?):
(PB 4.51)
InitNetwork()
port = 6832
*mem = AllocateMemory(36) ;<= Länge der Dateinamen
Repeat
SEvent = NetworkServerEvent()
If SEvent
clientID = EventClient()
Select SEvent
Case #PB_NetworkEvent_Data ;<=Dateiname wurden gesendet
ReceiveNetworkData(clientID,*mem,36)
file$ = PeekS(*mem,36) ; <= Dateiname wird gelesen
Case #PB_NetworkEvent_File
ReceiveNetworkFile(clientID,file$) ;<= Datei mit Dateinamen file$ wird empfangen
EndSelect
Else
Delay(2)
EndIf
ForEver
Nun quält mich aber folgender Gedanke: Client1 sendet also einen Dateinamen, der Server liest ihn aus. Das RecieveNetworkFile() kann aber erst bei einem weiteren Schleifendurchlauf irgendwann später ansprechen, da der Client1 die Datei ja erst noch versenden und ein neues ServerEvent generiert werden muß. Bevor nun aber der Client1 die Datei gesendet hat, schickt ein anderer Client, der Client2, schon den nächsten Dateinamen, den der Server auch brav empfängt. Wenn der Client1 dann die Datei sendet, wäre die Zuordnung des Dateinnamens wohl falsch, da würde die Datei vom Client1 mit dem vom Client2 gesendeten Namen gespeichert und von der Datei des Client2 mit dem selben Namen überschrieben.
Kann so etwas tatsächlich passieren und wenn ja, wie vermeidet man das?
Re: Wie Dateinanmen bei Datenübermittlung syncronisieren?
Verfasst: 02.11.2010 12:22
von Kiffi
Syntacks_Error hat geschrieben:wie vermeidet man das?
indem Du ausschliesslich Send- und ReceiveNetworkData() verwendest
Dann kannst Du Dateinamen und Datei (getrennt durch einen von Dir
definierten Separator) in einen Datenblock packen.
Timo hat angedeutet, dass Send- und ReceiveNetworkFile
in zukünftigen PB-Versionen ersatzlos gestrichen werden kann.
Grüße ... Kiffi
P.S.: Für Code-Schnippsel bitte auch das entsprechende Code-Tag
verwenden; nicht das Quote-Tag.
Re: Wie Dateinanmen bei Datenübermittlung syncronisieren?
Verfasst: 02.11.2010 12:27
von STARGÅTE
Vorab, für Codes gibs den Tag [ Code ], dafür Quote zu nutzen leuchtet mir nicht ein.
Zum Problem:
Du könntest an jeden Dateinamen-String, eine CRC32FileFingerprint() Nummer anhängen.
Damit kann der Empfänger prüfen, ob der Dateiname mit der CRC32FileFingerprint-Nummer, mit "seiner" Datei und seinem CRC32FileFingerprint übereinstimmt,
falls ja, gibt er der Datei den Namen,
falls nicht, sucht er entweder in den bereits empfangenen Datei (die zuvor temporär gespeichert wurden) ob noch eine nicht zugeordnet wurde, oder warten mit dem Dateinamen bis die passende Datei kommt.
Das, was du derzeit machst, ist auf jeden Fall nicht gut, weil du nicht sicher sein kannst, das der Dateiname immer vor der Datei ankommt, nur weil du ihn vorher schickst ...
Du solltest also auf jedenfall Listen anlegen, wo Dateinamen bzw Dateien in einer Warteschleife liegen können ... und nicht bei einem Emfang sofort speichern.
@Kiffi,
dann gäbe es andere Probleme das Datenblöcke gestückelt oder verkettet ankommen, dort müsste er dann noch die Länge mitsenden und halt prüfen ob ein Block zuende ist oder noch was fehlt ... (Separatoren bei Binärdaten gehen nicht ! Dort immer genau die Länge mitschicken)
Aber ich stimme zu SendNetworkData ist in allen Fällen die bessere Wahl ...
Re: Wie Dateinanmen bei Datenübermittlung syncronisieren?
Verfasst: 02.11.2010 13:00
von Syntacks_Error
Verlagert sich das Problem bei SendNetworkData() nicht nur? Größere Dateien - also gut, ich habe das Problem ja nicht, aber im Prinzip - müssen wegen der geringen Größe des Speichrpuffers in mehreren Blöcken gesendet werden. Auf der Empfangsseite tritt dann wieder genau das selbe Zuordnungsproblem auf, da ja nicht ausgeschlossen ist, daß sich ein anderer Client dazwischenmogelt. Braucht man da also tatsächlich immer eine Herkunftsangabe und eine Liste nebst Zwischenspeicherung aller Datenblöcke, woraus dann die Datei zusammengesetzt wird? Hört sich sehr umständlich an.
Re: Wie Dateinanmen bei Datenübermittlung syncronisieren?
Verfasst: 02.11.2010 13:23
von PureLust
Habe in PB noch nichts mit Netzwerkübertragung gemacht - von daher mal 2 Fragen in diesem Zusammenhang:
1. stellt das TCP/IP Protokoll nicht sicher, dass alle Pakete ankommen (und auch in der richtigen Reihenfolge)?
Soweit ich das mal gelesen habe kommen solche Probleme doch nur bei UTP vor.
2. Erhält man bei PB nicht Infos zu dem Client, der ein Netzwerkpaket schickt? Also kann man nicht unterscheiden von WEM ein Paket kommt?
(Kenne das zumindest von anderen Sprachen so.)
[Edit: 2. Frage hat sich soeben erledigt. EventClient() wird wohl das Zauberwort sein.)
Re: Wie Dateinanmen bei Datenübermittlung syncronisieren?
Verfasst: 02.11.2010 13:37
von STARGÅTE
Zu 1.
Ja bei TCP ist sichergestelt das Daten (nicht Pakete) die gesendet wurden auch ankommen.
Aber ich möchte hier noch mal darauf hinweisen, das es in PB keine Pakete in dem Sinne gibt!
Man kann immer nur (Binär-)Daten senden, und auch nur (Binär-)Daten empfangen.
Dabei landen jedoch alle Daten hintereinander weg im Empfangsbuffer des Clienten.
Dieser muss sich selbst darum kümmern die Daten wieder zu "entwirren".
bzw. muss der Sendet schon dafür sogen das seine sogenannten Pakete auch zu erkennen sind für andere.
Die Reihenfolge der Daten bleibt nur innerhalb einer Übertragung erhalten:
64Byte könnten zB als 30Byte und 34Byte ankommen, dort ist die Reihenfolge erhalten!
Zwei mal einzeln 32Byte zu senden heißt nicht, dass die erste Sendung auch zuerst ankommt.
Zu 2.
Ja PB kann jeden Client-Empfangsbuffer einzeln auslesen/überwachen.
Clienten können sich also nciht gegenseitig beeinflussen, aber "leider" sich selber.
Bei Dateien ist es aber eigentlich egal ob A123 B123 C123 als B123 A123 C123 empfangen wird.
Wichtig ist nur das aus A123 nicht 12A3 wird oder so, das ist jedoch bei TCP sichergestellt, wenn man es mit EINEM Send abschickt.
Also wie Kiffi sagte, ZB so:
PaketLänge+(DateiName+(DateiLänge+DateiBinärDaten)) in ein Buffer, diesen mit Send abschicken.
Auf der anderen Seite Paketlänge lesen, und solange Daten erfassen wie nötig.
dann den Buffer wieder aufsplitten und Datei mit Dateinamen erstellt.
Re: Wie Dateinanmen bei Datenübermittlung syncronisieren?
Verfasst: 07.11.2010 18:23
von PureLust
@STARGÅTE:
Vielen Dank, das war echt 'ne sehr informative und hilfreiche Erläuterung !!!
Gruß, PL.
Re: Wie Dateinanmen bei Datenübermittlung syncronisieren?
Verfasst: 07.11.2010 20:47
von Regenduft
STARGÅTE hat geschrieben:Clienten können sich also nciht gegenseitig beeinflussen, aber "leider" sich selber.
Was meinst Du mit "selbser beeinflussen"?
Re: Wie Dateinanmen bei Datenübermittlung syncronisieren?
Verfasst: 07.11.2010 20:55
von STARGÅTE
ich meine damit den einen Buffer den ein Client hat, indem nun mal alles reinkommt ...