Entwickler-Ecke
Internet / Netzwerk - Problem mit SocketComponente
Bergmann89 - Mo 26.03.07 11:35
Titel: Problem mit SocketComponente
HI,
ich hab ein Problem mit den Socketcomponenten:
Der fehler kommt:
kann mir jemand sagen woran das liegen könnte?
MfG & THX Bergmann.
p.s: Hab grad rausgefunden das es am Client liegt!
Fighter#1 - Mo 26.03.07 14:53
[glaskugel]
Ich würde sage es liegt an deiner negativen Aura
[/glaskugel]
Zeig uns deinen code, dann können wir dir helfen.
Sieht stark aus als wolltest du etwas senden und hast noch nicht verbunden!
Bergmann89 - Mi 28.03.07 11:33
HI,
ich hab den fehler gefunden, aber ich bekomm ihn nicht weg.
Ich hab ne Variable "Server" die is true wenn man server is.
und dann "if Server = False then ClientSendToSever"
Die Procedure sendet die daten vom Client an den Server.
Aber der Server führt die Procedure auch aus, obwohl ja vorher
die if-Abfrage steht. Hab auch mal nachgesehen, die Server-
Variable wird auf True gesetzt!
Das gesammte Projekt gibts hier:
DOWNLOAD (4,6MB) [
http://w12.easy-share.com/951849.html]
MfG Bergmann.
Narses - Di 03.04.07 21:38
Moin!
Ich kann das gesamte Projekt nicht runterladen (jedenfalls nicht, ohne Scripte auf der Download-Seite auszuführen - das werde ich aber nicht tun); warum hast du es nicht hier in den Anhang gepackt (ohne die EXE)?
Also habe ich mal kurz in dein Code-Archiv reingesehen, zugegeben nicht sonderlich "tief". Mir ist allerdings direkt aufgefallen, dass du z.B. sowas machst:
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:
| procedure TForm1.ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket); var ServerMessage:String; var Variables: Boolean; var Position: array of TVektor; var Speed: array of TVektor; var i:Integer; var Bitmap: TBitmap; begin ServerMessage := ClientSocket.Socket.ReceiveText; memo1.Text := Servermessage; Memo.Lines.SaveToFile('FromServer.log'); Variables := True;
if ServerMessage[1] = 'P' then begin delete(ServerMessage,1,1); Player := StrToInt(copy(ServerMessage,1,pos(',',ServerMessage)-1))-1; delete(ServerMessage,1,pos(',',ServerMessage)); Players := StrToInt(ServerMessage); Form2.IpLabel.Caption := Form2.IpLabel.Caption + chr(13) + 'Sie sind Spieler '+IntToStr(Player)+'.'; Form2.IpLabel.Caption := Form2.IpLabel.Caption + chr(13) + 'Es nehmen '+IntToStr(Players)+' Spieler am Spiel teil.'; Variables := False; end;
if ServerMessage = 'FULL' then |
a) Was passiert wohl, wenn du einen Leerstring aus dem Socket liest (was durchauch möglich ist!)? Genau, Exception bei ServerMessage[1]! :shock:
b) Du verlässt dich darauf, dass die Datenpakete zu den Ereignissen passen. Weit verbreiteter Irrtum,
siehe FAQ-Beitrag [
http://www.delphi-library.de/topic_Datenpakete+bei+den+SocketKomponenten+auseinanderhalten_56194.html]! :mahn:
cu
Narses
Bergmann89 - Mi 04.04.07 14:43
HI,
erstma Danke das du dich damit beschäftigt hast.
Das tutorial les ich mir gleich durch. Aber zuerst:
was meinst du mit "nicht sonderlich 'tief'" ?!
Und das gesamt Projekt passt nicht in den Anhang,
auch wenn ich die EXE rausnehm. Wenn ich die Images
noch raus nehm passts, dann habt ihr aber auch nix
anderes als den Quelltext. (und den habt ihr ja schon).
MfG Bergmann.
Narses - Mi 04.04.07 14:48
Moin!
Bergmann89 hat folgendes geschrieben: |
| was meinst du mit "nicht sonderlich 'tief'" ?! |
Ich hab mal über den Quelltext überflogen, aber nach deiner "Fehlerbeschreibung" kann ich da nix "erkennen"...
Bergmann89 hat folgendes geschrieben: |
| Und das gesamt Projekt passt nicht in den Anhang, |
Du kannst doch drei Dateien anhängen, teils halt auf. ;)
cu
Narses
Bergmann89 - Mi 04.04.07 19:40
Ich hab versucht es hoch zu laden, aber mein Modem kommt nicht hinterher.
Das müsste ich dann wieder in der Schule machen, aber zur Zeit sind Ferien.
Ich versuch jetzt ma mit deinem Netzwerk Protokoll, hab mir das Tutorial
geladen und arbeite das grad durch (bin Seite 26). An manchen Stellen n
bisl kompli, aber ansonsten gute Arbeit. Ma sehen ob's damit besser geht.
Wenn nicht dann mach ich wieder 2 verschiedene Programme, Server und Client
getrennt! Und wenns dann immer noch nicht geht, dann lass ich's sein, oder
ich meld mich nochma!
MfG Bergmann.
Bergmann89 - Do 05.04.07 18:02
So, hab mir jetzt das Tutorial soweit durchgearbeitet wie ich das für mein Projekt brauch. Hab jetzt aber ein Problem/eine Frage: Wenn ich die Daten als Integer weg schick:
Delphi-Quelltext
1: 2: 3: 4: 5:
| CmdSeq := TCmdSeq.Create(cmdSendPlayers); CmdSeq.Add(IntToStr(i)); CmdSeq.Add(IntToStr(Players)); ServerPA.Connections[i].Outbound.AddCmdAndFree(cmdSeq); ServerPA.Connections[i].Send; |
und dann auf der gegenseite versuch die wieder zu lesen:
Delphi-Quelltext
1: 2:
| Player := PA.Inbound.Strings[1]; Players := PA.Inbound.Strings[2]; |
dann meckert er wegen String und Integer rum!
Aber wenn ich die Daten vorher mit IntToStr in einen
String umwandel hättest du dir die Mühe mit den
einzelen Typen ja gar nicht machen brauchen?!
Also wie geht das denn nu ?! Das is das einzige wo ich
häng ansonsten müsste alles gehen und ich bin morgen
FERTSCH ^^
MfG Bergmann.
Narses - Do 05.04.07 23:19
Moin!
Bergmann89 hat folgendes geschrieben: |
| So, hab mir jetzt das Tutorial soweit durchgearbeitet wie ich das für mein Projekt brauch. |
Zunächstmal: wenn du nicht tiefer einsteigen willst, dann sind die
TNBFPA-Kompos [
http://www.delphi-forum.de/topic_TNBFPA+v103++SocketKompos+mit+Protokollfunktionen_71223.html] doch eigentlich genau richtig für dich. ;)
Dann zu deiner Frage:
Bergmann89 hat folgendes geschrieben: |
| Hab jetzt aber ein Problem/eine Frage: Wenn ich die Daten als Integer weg schick: |
Dann solltest du das auch tun: ;)
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| CmdSeq := TCmdSeq.Create(cmdSendPlayers); CmdSeq.Add(i); CmdSeq.Add(Players); ServerPA.Connections[i].Outbound.AddCmdAndFree(cmdSeq); ServerPA.Connections[i].Send;
------
Player := PA.Inbound.Strings[1]; Players := PA.Inbound.Strings[2]; |
cu
Narses
Bergmann89 - Fr 06.04.07 13:00
Ups, sorry der Quelltext war falsch...
Ich hatte das genau so wie du, dann hat er aber unten rumm gemeckert,
weil ja StringList[x] ein String ist und die Variable n Integer.
Deshalb hab ich das jetzt erstma so gemacht:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| CmdSeq := TCmdSeq.Create(cmdSendPlayers); CmdSeq.Add(IntToStr(i)); CmdSeq.Add(IntToStr(Players)); ServerPA.Connections[i].Outbound.AddCmdAndFree(cmdSeq); ServerPA.Connections[i].Send;
------
Player := StrToInt(PA.Inbound.Strings[1]); Players := StrToInt(PA.Inbound.Strings[2]); |
So geht ersma alles, bis auf die Datenübertragung
im Spiel, also wenn man dann mit den Autos rumfahren kann.
Ich hab das Projekt mal hochgeladen (aber ohne die Bilder
und Sounds). Ich wäre dir echt dankbar wenn du mir da nochma
helfen könntest.
MfG & Thx Bergmann.
Narses - Sa 07.04.07 00:08
Moin!
Bergmann89 hat folgendes geschrieben: |
| Ups, sorry der Quelltext war falsch... |
Dito... :oops:
Bergmann89 hat folgendes geschrieben: |
Ich hatte das genau so wie du, dann hat er aber unten rumm gemeckert,
weil ja StringList[x] ein String ist und die Variable n Integer. |
Eben, deshalb muss das beim Lesen auch so sein (das Tut war doch von mir, oder... :nut:):
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| CmdSeq := TCmdSeq.Create(cmdSendPlayers); CmdSeq.Add(i); CmdSeq.Add(Players); ServerPA.Connections[i].Outbound.AddCmdAndFree(cmdSeq); ServerPA.Connections[i].Send;
------
Player := PA.Inbound.AsInt[1]; Players := PA.Inbound.AsInt[2]; |
Bergmann89 hat folgendes geschrieben: |
| Ich hab das Projekt mal hochgeladen (aber ohne die Bilder und Sounds). Ich wäre dir echt dankbar wenn du mir da nochma helfen könntest. |
Ich werd mal reinschauen, aber ich verspreche nix. :?
cu
Narses
Bergmann89 - Sa 07.04.07 11:59
OK, trotzdem erstma VIELEN DANK!
Ich werd das mit dem "AsInt[x]" jetzt noch ändern...
Narses - So 08.04.07 01:36
Moin!
Bergmann89 hat folgendes geschrieben: |
So geht ersma alles, bis auf die Datenübertragung
im Spiel, also wenn man dann mit den Autos rumfahren kann. |
Witzbold, das ist ja nun auch der schwierige Teil... :P
Hast du eigentlich nicht bemerkt, dass der Compiler 2 Warnungen im Server-Code ausgibt: :gruebel:
| Compiler hat folgendes geschrieben: |
| [Warnung] Unit1.pas(106): FOR-Schleifenvariable 'i' kann nach Durchlauf undefiniert sein |
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:
| procedure TNBFPAServer.ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket); var i: Integer; CmdSeq: TCmdSeq; begin i := ServerPA.IndexOfSocket(Socket); LogIt('+ SID:'+IntToStr(ServerPA.Connections[i].SessionID)+ ' verbunden mit '+Socket.RemoteAddress); CmdSeq := TCmdSeq.Create(cmdVERSION); CmdSeq.Add(APPID_SRV); CmdSeq.Add(IntToStr(PROTO_VER)); CmdSeq.Add(IntToStr(PROTO_REV)); with ServerPA.Connections[i] do begin Outbound.AddCmdAndFree(CmdSeq); Send; end;
if Players < 10 then begin inc(Players); SetLength(ClientReady,Players); for i := 0 to ServerSocket1.Socket.ActiveConnections-1 do ClientReady[i] := False; CmdSeq := TCmdSeq.Create(cmdSendPlayers); CmdSeq.Add(IntToStr(i)); CmdSeq.Add(IntToStr(Players)); ServerPA.Broadcast(cmdSeq); end else begin CmdSeq := TCmdSeq.Create(cmdFullServer); ServerPA.Connections[i].Outbound.AddCmdAndFree(CmdSeq); ServerPA.Connections[i].Send; end; end; |
| Compiler hat folgendes geschrieben: |
| [Warnung] Unit1.pas(137): Variable 'i' ist möglicherweise nicht initialisiert worden |
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| procedure TNBFPAServer.ServerSocket1ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket); var i: Integer; CmdSeq: TCmdSeq; begin DeleteClient(Socket); dec(Players); Log.Lines.Add(IntToStr(Players)); SetLength(ClientReady,Players); CmdSeq := TCmdSeq.Create(cmdSendPlayers); CmdSeq.Add(IntToStr(i)); CmdSeq.Add(IntToStr(Players)); ServerPA.Broadcast(CmdSeq); end; |
Behebe doch noch bitte diese beiden potentiellen Fehler und gib dann noch eine
exakte Fehlerbeschreibung an, was nicht funktioniert (also sowas wie "wenn ich da was mache, dann geht das nicht" wäre vermutlich nicht geeignet, meine Motivation DEINE FEHLER zu suchen, zu heben... :mahn:)
cu
Narses
Bergmann89 - Di 10.04.07 18:49
so, die fehler mit dem "i" sind erstma raus...
Jetzt zu dem anderen Problem:
hiermit werden die Daten formatiert und gesendet:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| procedure SendData; var CmdSeq: TCmdSeq; begin CmdSeq := TCmdSeq.Create(cmdClientDaten); CmdSeq.Add(IntToStr(Player)); CmdSeq.Add(FloatToStr(Cars[Player].Position.x * 100 / Screen.Width)); CmdSeq.Add(FloatToStr(Cars[Player].Position.y * 100 / Screen.Height)); CmdSeq.Add(FloatToStr(Cars[Player].Speed.x * 100 / Screen.Width)); CmdSeq.Add(FloatToStr(Cars[Player].Speed.y * 100 / Screen.Height)); PA.Outbound.AddCmdAndFree(CmdSeq); PA.Outbound.SaveToFile('ToServer.log'); PA.Send; end; |
dann kommen sie beim Server rein und der schickt sie weiter an alle Clienten:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| cmdClientDaten: begin CmdSeq := TCmdSeq.Create(cmdClientDaten); PA.Inbound.SaveToFile('FromClient.log'); CmdSeq.Add(Pa.Inbound.Strings[1]); CmdSeq.Add(Pa.Inbound.Strings[2]); CmdSeq.Add(Pa.Inbound.Strings[3]); CmdSeq.Add(Pa.Inbound.Strings[4]); CmdSeq.Add(Pa.Inbound.Strings[5]); ServerPA.Broadcast(CmdSeq); end; |
und bei den Clienten werden sie wieder auseinander genmommen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| cmdClientDaten: begin PA.Outbound.SaveToFile('FromServer.log'); if StrToInt(PA.Inbound.Strings[1]) <> Player then begin i := StrToInt(PA.Outbound.Strings[1]); Cars[i].Position := Vektor(Screen.Width / 100 * StrToFloat(PA.Inbound.Strings[2]), Screen.Height / 100 * StrToFloat(PA.Inbound.Strings[3])); Cars[i].Speed := Vektor(Screen.Width / 100 * StrToFloat(PA.Inbound.Strings[4]), Screen.Height / 100 * StrToFloat(PA.Inbound.Strings[5])); end; end; |
Anhand der *.log-Datein (im Anhang) kann man auch sehen das die Daten korrekt ankommen.
Also müsste das so gehen, aber es geht nicht. Ich hab das schonma so gemacht und da hat
es gefunzt, deshalb weiß ich jetzt hier nicht weiter...
Narses - Di 10.04.07 19:28
Moin!
Ich kann das Client-Projekt nicht starten... :? pack doch mal den Inhalt des Ordners material\ in ein ZIP und dann hier in den Anhang (wozu du die EXE drin hast, aber nicht die NOTWENDIGEN Dateien, ist mir auch noch nicht ganz klar... :gruebel:)
cu
Narses
//EDIT: hab mir jetzt dummy-Images erzeugt und das ganze Bass/MPlayer-Zeugs rausgeworfen, um das Projekt überhaupt starten zu können - aber, jetzt habe ich ein komisches Formular ohne Controls und kann nix machen, ausser mit ESC rausgehen... :( WIE KANN MAN DENN DIESES WUNDERVOLLE PROGRAMM ÜBERHAUPT DAZU BRINGEN IRGENDWAS ZU TUN :?!?:
//EDIT2: Dein Code und Programmierstil sind... vorsichtig gesagt... zum :bawling: :hair: (du solltest DRINGEND darüber nachdenken, ob globale Variablen wirklich in der Menge NOTWENDIG sind, in der du sie verwendest; auch was die Performance deines Codes angeht, ist das sicherlich nicht besonders gut, z.B. lädst du viel zu oft Bitmaps von der Platte, warum z.B. keine ImageListen oder OffScreenBitmaps?! du hast auch kaum Sicherheitsleinen im Code...)
Schätze, ich bin trotzdem aus versehen über den entscheidenden Fehler gestolpert: 8) :D
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| procedure TForm1.ExecuteCmd(PA: TProtocolAdapter); [...] cmdClientDaten: begin PA.Outbound.SaveToFile('FromServer.log'); if StrToInt(PA.Inbound.Strings[1]) <> Player then begin i := StrToInt(PA.Outbound.Strings[1]); Cars[i].Position := Vektor(Screen.Width / 100 * StrToFloat(PA.Inbound.Strings[2]), Screen.Height / 100 * StrToFloat(PA.Inbound.Strings[3])); Cars[i].Speed := Vektor(Screen.Width / 100 * StrToFloat(PA.Inbound.Strings[4]), Screen.Height / 100 * StrToFloat(PA.Inbound.Strings[5])); end; end; |
Da muss doch wohl
Inbound stehen, oder? :zwinker:
Ich versuche jetzt bestimmt seit 1,5h einfach nur das Projekt (und da auch nur den Client) soweit zu strippen, dass es sich einfach nur starten läßt und nicht sofort bei der kleinsten Aktion irgendwas vor die Wand läuft... :autsch: :roll: Wenn´s das nicht ist, dann fürchte ich, dass ich keine Lust mehr habe, nach weiteren Fehlern zu suchen (sorry, aber dein Code ist mir einfach zu chaotisch, da sucht man sich ja tot)... :| :?
cu
Narses
Bergmann89 - Do 12.04.07 11:50
HI,
hab den Fehler auch grad gefunden, eigentlich ganz schön dumm :oops:
Aber jetztmüsste es gehen, werd dann mal n Test durchführen...
Und nun mal zu meinem Code: Ich weiß, das er nicht grad der beste ist, aber
für einen der bloß 12. Klasse InfoGrundkurs is, is das schon n sehr großes
Projekt und zur Zeit hab ich da all mein wissen reingepackt ^^
Das mit den ImageListen hab ich auch probiert, das sah so aus:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| var images: array[0..9,0..5] of TBitmap; CarTex: TBitmap
for i := 0 to 9 do for j := 0 to 5 do begin images[i,j] := TBitmap.Create; images[i,j].LoadFromFile('material\cars\car'+IntToStr(i)+'_'+IntToStr(j)+'.bmp'); end;
CarTex := images[x,y]; RotateBitmap(CarTex,..... |
Wenn ich das so mach, dan dreht er die Bitmap die in Images drin ist,
und dann wird die total verunstaltet, da der die nicht neu läd...
Und sowas wie ReadOnly gibts da ja nicht!
MfG Bergmann
p.s.: ich hab den Beitrag zwar schonma geschrieben, aber irgendwie is der wieder weg^^
Narses - Do 12.04.07 12:04
Moin!
Nochmal der Hinweis: Warum verwendest du nicht die TNBFPA-Kompos von mir, statt der Unit-Version aus dem Tut?! Das macht es dir sicher etwas einfacher und auch den Code übersichtlicher. ;)
Eigentlich ja neue Frage, neuer Thread! :mahn: Da du das (neue) Thema aber gar nicht angesprochen hast, sondern ich :nut: trotzdem schnell was dazu: ;)
Bergmann89 hat folgendes geschrieben: |
Das mit den ImageListen hab ich auch probiert, das sah so aus:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| var images: array[0..9,0..5] of TBitmap; CarTex: TBitmap
for i := 0 to 9 do for j := 0 to 5 do begin images[i,j] := TBitmap.Create; images[i,j].LoadFromFile('material\cars\car'+IntToStr(i)+'_'+IntToStr(j)+'.bmp'); end;
CarTex := images[x,y]; RotateBitmap(CarTex,..... | |
Du kannst Objekte nicht mit einer direkten Zuweisung kopieren, das geht so: ;) :idea:
Delphi-Quelltext
1:
| CarTex.Assign(images[x,y]); |
cu
Narses
Bergmann89 - Do 12.04.07 12:25
AHHH, wieder was dazu gelernt ^^
Werd mir die TNBFPA-Kompos mal ansehen und einbauen, wenns noch
Probleme gibt, oder es dann endlich fertig ist, meld ich mich nochma!
MfG Bergmann.
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!