Entwickler-Ecke
Internet / Netzwerk - keine Datenübertragung
*Eldorado - Sa 23.04.11 13:27
Titel: keine Datenübertragung
hi,
ich hab mir ein tutorial zu TServerSockel und TClientSockel duchgelesen und dementsprechend einen Client und einen Server geschrieben. Jetzt habe ich das problem, das die gesendeten Informationen via Socket.ReceiveText und Socket.SendText(), sowie Socket.SendBuf() nicht ankommen bzw nicht verarbeitet werden.
Wo habe ich den Fehler?
Hier sind die relevanten auszüge aus den Sourcen:
Server:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| procedure TfAnwendung.ServerClientRead(Sender: TObject; Socket: TCustomWinSocket); var User:CustomRec; begin if Server.Socket.ReceiveText = 'On' then begin Server.Socket.ReceiveBuf(User,SizeOf(User)); if CheckPW(User) = true then EditOnline(true,User); end; if Server.Socket.ReceiveText = 'off' then begin Server.Socket.ReceiveBuf(User,SizeOf(User)); if CheckPW(User) = true then EditOnline(false,User); end;
end;
procedure TfAnwendung.ServerClientConnect(Sender: TObject; Socket: TCustomWinSocket); begin ShowMessage('Verbunden'); end; |
Die Procedure ServerClientConnect funktioniert einwandfrei, Syntaxfehler bekomme ich auch nicht.
Client:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32:
| procedure TfAnwendung.bAusClick (Sender: TObject); begin Client.Open; Client.Socket.SendText('off'); Client.Socket.SendBuf(User,Sizeof(User)); Client.Close; bEin.Visible:=true; bNew.Visible:=true; lePW.Visible:=true; leUser.Visible:=true; bAus.Visible:=false; Image1.Visible:=false; end;
procedure TfAnwendung.bEinClick (Sender: TObject); begin User.User:=leUser.Text; User.PW:=lePW.Text; User.IP:=PowerSock1.LocalIP; Client.Open; Client.Socket.SendText('On'); Client.Socket.SendBuf(User,Sizeof(User)); Client.Close; end;
procedure TfAnwendung.FormCreate(Sender: TObject); begin Client.Port:=10066; Client.Host:='127.0.0.1'; end; |
Btw: User ist ein Rec.
& Die Meldung der Verbindungen erscheinen.
Moderiert von
Martok: Code- durch Delphi-Tags ersetzt
*Eldorado - Sa 23.04.11 14:08
Ja die Meldung kommt. (gleich schnell oben editieren^^)
jaenicke - Sa 23.04.11 14:25
Hast du einmal einen Haltepunkt in ServerClientRead gesetzt? Kommt das Programm dort an? Und wenn ja, was passiert dann?
// EDIT:
Wenn ich mich recht entsinne, darf ReceiveText nicht mehrfach aufgerufen werden, oder?
*Eldorado - Sa 23.04.11 14:40
jaenicke hat folgendes geschrieben : |
| Hast du einmal einen Haltepunkt in ServerClientRead gesetzt? Kommt das Programm dort an? Und wenn ja, was passiert dann? |
Ja habe ich, es fängt nichts an.
jaenicke hat folgendes geschrieben : |
Wenn ich mich recht entsinne, darf ReceiveText nicht mehrfach aufgerufen werden, oder? |
Keine ahnung, ich kenn mich damit net aus.
jaenicke - Sa 23.04.11 18:23
*Eldorado hat folgendes geschrieben : |
| Ja habe ich, es fängt nichts an. |
Dann überprüfe einmal, ob die Firewall blockiert oder ähnliches. Denn wenn das Ereignis nicht einmal ausgelöst wird...
Warum schließt du eigentlich die Verbindung zum Server sofort wieder? Willst du nicht mehr machen als einmalig das zu schicken? :shock:
*Eldorado hat folgendes geschrieben : |
jaenicke hat folgendes geschrieben : |
Wenn ich mich recht entsinne, darf ReceiveText nicht mehrfach aufgerufen werden, oder? |
Keine ahnung, ich kenn mich damit net aus. |
Ich habe kurz nachgeschaut. :roll:
Wie ich dachte, das ist eine Methode, die direkt den Text abruft. Rufst du es erneut auf, wird der
nächste Text angefragt...
Du musst also den Text z.B. in einer lokalen Stringvariable zwischenspeichern.
Davon abgesehen:
*Eldorado hat folgendes geschrieben : |
Delphi-Quelltext 1: 2: 3: 4: 5:
| procedure TfAnwendung.ServerClientRead(Sender: TObject; Socket: TCustomWinSocket); var User:CustomRec; begin if Server.Socket.ReceiveText = 'On' then begin | |
Äußerst logisch... Du bekommst einen Socket übergeben, ignorierst den aber und nutzt irgendeinen anderen...
Das kann nicht klappen, was, wenn mehrere Verbindungen ankommen?
Also:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure TfAnwendung.ServerClientRead(Sender: TObject; Socket: TCustomWinSocket); var ReceivedText: string; begin ReceivedText := Socket.ReceiveText; if ReceivedText = 'On' then begin
end else ... |
Mr_Emre_D - So 24.04.11 00:27
1. Warum Verbindungen öffnen und anschließend direkt wieder schließen? Ich sehe nicht viel Sinn dahinter.
Du scheinst etwas fundamental falsch verstanden zu haben, was mir das hier zeigt:
Delphi-Quelltext
1: 2:
| if Server.Socket.ReceiveText = 'On' then begin Server.Socket.ReceiveBuf(User,SizeOf(User)); |
2. Du musst dir das Senden und Empfangen von Daten so vorstellen:
Nimm dir ein Glas und stell es unter einen Wasserhahn und öffne den Wasserhahn. Nun fließt konstant Wasser hinein.
Wenn du das Glas nicht wegnimmst (entleerst->ReceiveText), wirds immer voller.
Nun kannste dir den Wasserhahn als "Sender" und das Glas als "Empfänger" vorstellen. Das Wasser ist der Datenfluss ("Stream") der unter Umständen ständig geschickt bzw. empfangen wird (solange halt Wasser durchfließt - dh. solange Daten vorhanden sind, bzw. geschickt werden).
Wenn du jetzt einmal ReceiveText aufrufst, aber dein Sender schon 'On' UND User geschickt hat, wird dir ReceiveText den ganzen String, dh. 'On<User>' zurückliefern.
Da hilft dann die Abfrage = 'On' nicht mehr, da kein 'On' allein ankommt! Dein Glas ist voll und wird immer voller!
Daher musst du dir überlegen, wie du Datensätze als Pakete interpretieren kannst. Diese kommen zwar als Pakete an, werden aber dann in den Puffer angehangen (gequeued) und der Puffer wächst und wächst, was zu Folge hat, dass du nicht mehr erkennen kannst, wo etwas beginnt und wo es endet.
Am einfachsten ist soetwas, wenn man einfach einen Seperator verwendet wie z.B. '#'.
Dann musst du das Angekommene eben parsen und schauen, ob du einen Datensatz aus dem Stream mit '#' am Ende rausfischen kannst um anschließend darauf zu reagieren.
Ein Beispiel, wie das dann aussähe:
User = 'Eldorado'.
du schickst 'On#'
du schickst User + '#' (='Eldorado#')
-
du empfängst 'On#Eldorado#';
du kopierst wiederholterweise alles bis zu # und entfernst alle Zeichen bis diesem inklusive -->
1. 'On'
2. 'Eldorado'
Boldar - So 24.04.11 08:22
Ich verweise auch mal auf die Umfangreichen Tutorials hier in der Library, besonders auf das Terminatorzeichen-Tutorial von Narses.
*Eldorado - So 24.04.11 09:54
jaenicke hat folgendes geschrieben : |
*Eldorado hat folgendes geschrieben : | | Ja habe ich, es fängt nichts an. | Dann überprüfe einmal, ob die Firewall blockiert oder ähnliches. Denn wenn das Ereignis nicht einmal ausgelöst wird... |
Die Firewall hab ich ausgeschaltet gehabt.
jaenicke hat folgendes geschrieben : |
Warum schließt du eigentlich die Verbindung zum Server sofort wieder? Willst du nicht mehr machen als einmalig das zu schicken? :shock: |
Mr_Emre_D hat folgendes geschrieben : |
| 1. Warum Verbindungen öffnen und anschließend direkt wieder schließen? Ich sehe nicht viel Sinn dahinter. |
naja, es ist ja noch nicht fertig und zur zeit wird halt mehr noch nicht übertragen.
jaenicke hat folgendes geschrieben : |
*Eldorado hat folgendes geschrieben : | jaenicke hat folgendes geschrieben : |
Wenn ich mich recht entsinne, darf ReceiveText nicht mehrfach aufgerufen werden, oder? |
Keine ahnung, ich kenn mich damit net aus. | Ich habe kurz nachgeschaut. :roll:
Wie ich dachte, das ist eine Methode, die direkt den Text abruft. Rufst du es erneut auf, wird der nächste Text angefragt...
Du musst also den Text z.B. in einer lokalen Stringvariable zwischenspeichern. |
okay, ich versuchs gleich mal anzupassen.
naja das müsste sich mit der zwischenvariable ja auch mit erledigen oder?
jaenicke hat folgendes geschrieben : |
Also: Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure TfAnwendung.ServerClientRead(Sender: TObject; Socket: TCustomWinSocket); var ReceivedText: string; begin ReceivedText := Socket.ReceiveText; if ReceivedText = 'On' then begin
end else ... | |
Mr_Emre_D hat folgendes geschrieben : |
Am einfachsten ist soetwas, wenn man einfach einen Seperator verwendet wie z.B. '#'.
Dann musst du das Angekommene eben parsen und schauen, ob du einen Datensatz aus dem Stream mit '#' am Ende rausfischen kannst um anschließend darauf zu reagieren.
Ein Beispiel, wie das dann aussähe:
User = 'Eldorado'.
du schickst 'On#'
du schickst User + '#' (='Eldorado#')
-
du empfängst 'On#Eldorado#';
du kopierst wiederholterweise alles bis zu # und entfernst alle Zeichen bis diesem inklusive -->
1. 'On'
2. 'Eldorado' |
Sieht interesannt aus, mal schaun ob ichs umsetzten kann.
Auf an die arbeit und umbasteln.
---
Moderiert von
Narses: Beiträge zusammengefasst---
So, ich hab jetzt mal ein wenig umgebastelt und mich entschlossen erstmal auf das SendBuf zu verzichten, da ich die syntax da sowieso nicht wirklich verstanden habe.
Jetzt läuft alles über SendText.
Desweiteren hab ich einfach mal die ganze komunikation in einem Memo mitschreiben lassen, wobei mir aufgefallen ist, das der Login text garnicht übertragen wird, aber der logoff, wobei beide eigentlich fast gleich aufgebaut sind.
Client:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
| procedure TfAnwendung.bAusClick (Sender: TObject); begin Client.Open; Client.Socket.SendText('off#'+User.User+'#'+User.PW+'#'+User.IP+'#'); Client.Close; end;
procedure TfAnwendung.bEinClick (Sender: TObject); begin User.User:=leUser.Text; User.PW:=lePW.Text; User.IP:=PowerSock1.LocalIP; Client.Open; Client.Socket.SendText('stupid!'); Client.Socket.SendText('On#'+User.User+'#'+User.PW+'#'+User.IP+'#'); Client.Close; end;
procedure TfAnwendung.FormCreate(Sender: TObject); begin Client.Port:=10066; Client.Host:='127.0.0.1'; end; |
Server:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57:
| procedure TfAnwendung.FormCreate(Sender: TObject); begin Server.Port:=10066; Server.Open; end;
procedure TfAnwendung.ServerClientRead(Sender: TObject; Socket: TCustomWinSocket); var User:CustomRec; MSG:string; tick:integer; todo:boolean; begin User.User:=''; User.PW:=''; User.IP:=''; MSG := Socket.ReceiveText; Memo1.Lines.Add(MSG); while (MSG[tick] <> '#') do begin if (MSG[tick] = 'o') and (MSG[tick+1] = 'n') and (MSG[tick+2] = '#') then todo:=true; if (MSG[tick] = 'o') and (MSG[tick+1] = 'f') and (MSG[tick+2] = 'f') and (MSG[tick+3] = '#') then todo:=false; inc(tick); end; inc(tick,3); if todo = false then inc(tick);
while MSG[tick] <> '#' do begin User.User:=User.User+MSG[tick]; inc(tick); end; inc(tick);
while MSG[tick] <> '#' do begin User.PW:=User.PW+MSG[tick]; inc(tick); end; inc(tick);
while MSG[tick] <> '#' do begin User.IP:=User.IP+MSG[tick]; inc(tick); end;
if CheckPW(User) = true then EditOnline(todo,User); end;
procedure TfAnwendung.ServerClientConnect(Sender: TObject; Socket: TCustomWinSocket); begin ShowMessage('Verbunden'); end;
end. |
Nachwievor funktioniert ClientConnect.
Narses - So 24.04.11 23:49
Moin!
*Eldorado hat folgendes geschrieben : |
| ich hab mir ein tutorial zu TServerSockel und TClientSockel duchgelesen und dementsprechend einen Client und einen Server geschrieben. |
Wenn ich mir den Code so ansehe, dann solltest du das Tutorial besser schnell wieder weglegen... :?
(min.) Zwei entscheidende Probleme:
*Eldorado hat folgendes geschrieben : |
| Hier sind die relevanten auszüge aus den Sourcen: |
Leg den Code bei Seite, das kann man nicht mehr retten. :| (alleine der Umgang mit dem Client-Socket ist eine Katastrophe - oder synchron beabsichtigt, aber jedenfalls nicht offensichtlich erkennbar, es fehlen dann ja auch die Exception-Handler)
cu
Narses
FrEaKY - Mo 25.04.11 19:59
Das schreit nach einem Protokoll... zumindest ein simples.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!