Entwickler-Ecke

Internet / Netzwerk - PeerToPeer Nutzen im Chat


MaikPoP - Fr 25.12.09 19:07
Titel: PeerToPeer Nutzen im Chat
Ich habe mir Überlegt ob es gehen würde ein PeerToPeer Chat zu Schreiben mit Delphi? oder brauch ich eine zusätzliche P2PKomponente? denn P2P ist doch wenn ich mich nicht irre Server und Client Sockets auf einer form??? Wie fang ich da am besten an? giebt es dazu ein Thread? ich habe auch schon bei google gesucht und hab nur was von GNUC.dll was gefunden.



Lg Maik


MaikPoP - Fr 25.12.09 23:16

Weiß denn keiner ein Raht zu diesem Thema


Niko S. - Fr 25.12.09 23:24

Nur weil du in 4 Stunden keine Antwort bekommen hast, ist das doch lang kein Grund einen Doppelpost zu machen.
Eigentlich könnte das so Funktionieren, aber das müsste ja auch anders Funktioniere, du brauchst ja nur eine Verbindung.
Also der der Verbindet, ist "Server" und der den du ansprichst "Client".
Was du dir dabei anschauen solltest ist, wie man UPD löcher durch die Firewall schießt...


MaikPoP - Fr 25.12.09 23:41

Upps Sorry

Meinst du so was wie "Firewall(Port) Forwarding"??? Dann brauch ich für ein P2PChat keine spezielle Komponente?





Lg Maik


FinnO - Fr 25.12.09 23:42

sollte da nicht ein Host/Client Konzept ausreichen, wie auch bei Multiplayergames der Fall? Ein Mitchatter eröffnet die Session, erzeugt sich also dynamisch den Server/aktiviert den Server und der andere kann dann als Client beitreten...


MaikPoP - Sa 26.12.09 18:32

Ich habe es mal so Versucht mit Hilfe von Narses Tutorial. Ein Server beim Program Start zu starten läuft auch. Dann per Klick auf Nutzer liste einen client zu Erzeugen und da ist etwas nicht ganz richtig nur ich weiß einfach nicht was.


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:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
type
  TClient = class
  private
   CliSocket : TClientSocket;
   procedure CliSocketRead(ASender: TObject; Socket: TCustomWinSocket);
   procedure CliSocketError(ASender: TObject; Socket: TCustomWinSocket;
   ErrorEvent: TErrorEvent; var ErrorCode: Integer);
   procedure CliSocketConnect(ASender: TObject; Socket: TCustomWinSocket);
   procedure CliSocketDisconnect(ASender: TObject; Socket: TCustomWinSocket);
  Public
   Constructor CreateNewSession(IP, UserID :string); reintroduce;
end;

Type
  TForm2 = class(TForm)
    GroupBox1: TGroupBox;
    PageControl1: TPageControl;
    ToolBar1: TToolBar;
    ToolButton1: TToolButton;
    ToolButton2: TToolButton;
    ToolButton3: TToolButton;
    ToolButton4: TToolButton;
    ImageList1: TImageList;
    ToolBar2: TToolBar;
    ToolButton5: TToolButton;
    ToolButton6: TToolButton;
    ToolButton7: TToolButton;
    Memo1: TMemo;
    ImageList2: TImageList;
    LMDSimplePanel1: TLMDSimplePanel;
    Image1: TImage;
    SpeedButton1: TSpeedButton;
    SpeedButton2: TSpeedButton;
    StaticText1: TStaticText;
    LMDSimplePanel2: TLMDSimplePanel;
    LMDSpeedButton1: TLMDSpeedButton;
    Log: TMemo;
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    Procedure CreateNewTab(UserID:String);

    procedure ParseBuffer;
    function GetCmdToken(const StrToken: String): TCmdToken;
    procedure ExecuteX(const Command: TCmdToken; Data: TStringList);
  end;



var
  Form2: TForm2;

  ReceiveBuffer: String// Empfangspuffer
  Tab: TTabSheet;
  WB: TWebbrowser;

  ASender: TObject;
  Socket: TCustomWinSocket;
  ErrorEvent: TErrorEvent;
  ErrorCode: Integer;

implementation
uses Unit1;
{$R *.dfm}

// Empfangspuffer nach Befehlen durchsuchen und dann ausführen
procedure TForm2.ParseBuffer;
  var
    Data: TStringList; // zum Zerlegen des Empfangspuffers
    Current: TCmdToken; // aktuelles Kommando
    OutOfArg: Boolean; // Flag zum Abbrechen der Befehlssuche
begin
  Data := TStringList.Create;
  try
    Data.Text := ReceiveBuffer; // Empfangspufferdaten in Pakete zerlegen
    OutOfArg := FALSE; // wir nehmen mal an, es sind genug Argumente da
    while ( (Data.Count > 0// solange noch Befehle da sind und
            and (NOT OutOfArg) ) do begin // die Argumente dafür reichen
      // Befehl erkennen (gross/klein egal)
      Current := GetCmdToken(UpperCase(Data.Strings[0]));
      // ausreichend Argumente dafür da?
      if (Data.Count >= Syntax[Current].ArgCount) then
        ExecuteX(Current,Data) // ja, dann bearbeiten
      else // nein -> auf neue Daten warten...
        OutOfArg := TRUE;
    end;
    // noch nicht verarbeitete Werte wieder in den Puffer zurück
    ReceiveBuffer := Data.Text;
  finally
    Data.Free;
  end;
end;

// Befehlstoken zu übergebenem String suchen
function TForm2.GetCmdToken(const StrToken: String): TCmdToken;
begin
  Result := Low(Syntax); // erster Befehl
  while ( (Result < cmdERROR) // solange noch nicht alle Befehle durch sind
          and                 // und
          (StrToken <> Syntax[Result].Text) ) do // der Befehl nicht passt
    Inc(Result); // nächsten Befehl nehmen
  // Die Schleife bricht spätestens bei cmdERROR ab
end;

// Befehle ausführen; die notwendige Anzahl Argumente ist garantiert
procedure TForm2.ExecuteX(const Command: TCmdToken; Data: TStringList);
  var
    i: Integer;
begin
  case Command of
    cmdNOP: ;
    cmdSAID: Log.Lines.Add(Data.Strings[1]+': '+Data.Strings[2]);
    cmdUSER: form1.Clients.Items.CommaText := Data.Strings[1];
    cmdIP:   form1.Clients.Items.CommaText := Data.Strings[1];
    else
      form1.WriteEvLog('Unbekanntes Kommando: '+Data.Strings[0]);
  end;
  for i := 1 to Syntax[Command].ArgCount do
    Data.Delete(0);
end;

Procedure TForm2.CreateNewTab(UserID:String);
begin
 Tab := TTabsheet.Create(self);
 Tab.PageControl := PageControl1;
 Tab.Caption := UserID;
 Tab.Name := 'TabX' + IntToStr(PageControl1.PageCount);
 PageControl1.ActivePage := Tab;
 WB := TWebbrowser.Create(self);
 TControl(WB).Parent := Tab;
 TControl(WB).Name := 'Webbrowser' + IntToStr(PageControl1.PageCount);
 WB.Visible := true;
 WB.Align := alClient;
end;

Constructor TClient.CreateNewSession(IP, UserID :string);
begin
 CliSocket := TClientSocket.Create(nil);
 try
  CliSocket.OnConnect(ASender, Socket);
  CliSocket.OnDisconnect(ASender, Socket);
  CliSocket.OnError(ASender, Socket,ErrorEvent,ErrorCode);
  CliSocket.OnRead(ASender, Socket);

 with CliSocket do
 begin
  Name := 'Cli_'+UserID;
  Port := Server_port;
  Host := IP;
  Active := true;
 end;
 except
  exit;
 end;
end;

// Daten vom Server empfangen
procedure TClient.CliSocketRead(ASender: TObject; Socket: TCustomWinSocket);
begin
  ReceiveBuffer := ReceiveBuffer +Socket.ReceiveText; // Daten lesen
  if (ReceiveBuffer <> ''then // wenn Daten da sind...
    form2.ParseBuffer; // ...versuchen, Befehle auszuführen
end;

// Es ist ein Fehler in der Verbindung aufgetreten; sicherheitshalber trennen
procedure TClient.CliSocketError(ASender: TObject; Socket: TCustomWinSocket;
  ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
  ErrorCode := 0// Fehler behandelt, keine Exception erzeugen
  form2.Log.Lines.Add('Verbindungsfehler!');
end;

// Verbindung zum Server ist aufgebaut und bereit zum Senden/Empfangen
procedure TClient.CliSocketConnect(ASender: TObject; Socket: TCustomWinSocket);
begin
  ReceiveBuffer := ''// Empfangspuffer initialisieren
  form2.Log.Clear; // Protokollfenster löschen
  form2.Log.Lines.Add('Verbunden mit: '+CliSocket.Host);
  // noch den eigenen Nickname senden
  Socket.SendText(Syntax[cmdNICK].Text+#13+form1.LabeledEdit1.Text+#13);
end;

// Verbindung zum Server (normal) getrennt
procedure TClient.CliSocketDisconnect(ASender: TObject;
  Socket: TCustomWinSocket);
begin
  form1.Clients.Clear; // User-Liste leeren
  form2.Log.Lines.Add('Verbindung getrennt.');
end;
end.


aber irgend wie bekomme ich nur Fehler Meldung das der Port nur Einmal Genutzt werden darf und

Zitat:

Im Projekt ist eine Exception der Klasse EAccessViolation aufgetreten. Meldung: Zugriffsverletzung bei Adresse 00000000. Lesen von Adresse 00000000. Process wurde Angehalten.


ich denke mal das ich da irgend wo was Vergessen habe oder :?:

Schaut euch das mal bitte an vllt findet ihr ja den Fehler.

Lg Maik


Flamefire - Sa 26.12.09 20:53

Also:
Als erstes debuggen und sagen, in welcher zeile der fehler kommt.
Hier ist es zum glück klar:


Delphi-Quelltext
1:
2:
3:
4:
  CliSocket.OnConnect(ASender, Socket);
  CliSocket.OnDisconnect(ASender, Socket);
  CliSocket.OnError(ASender, Socket,ErrorEvent,ErrorCode);
  CliSocket.OnRead(ASender, Socket);

Damit rufst du funktionen auf!
Du wolltest sie aber zuweisen!


MaikPoP - Sa 26.12.09 23:03

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
Also:
Als erstes debuggen und sagen, in welcher zeile der fehler kommt.
Hier ist es zum glück klar:


Delphi-Quelltext
1:
2:
3:
4:
  CliSocket.OnConnect(ASender, Socket);
  CliSocket.OnDisconnect(ASender, Socket);
  CliSocket.OnError(ASender, Socket,ErrorEvent,ErrorCode);
  CliSocket.OnRead(ASender, Socket);

Damit rufst du funktionen auf!
Du wolltest sie aber zuweisen!


Er hat mir ja keine Zeile Angegeben nur halt das er ein Fehler Gefunden hat nur wo sagt er mir net.

Aber bei Console schreibt man das doch auch oder nicht wenn die Komponente werend der laufzeit erstellt wird?
Wie kann ich das denn noch schreiben denn ich brauch doch die Angaben im Chat? habe kein Plan :cry:


Sorry das ich so dumm Frage bei diesem Thema aber ich habe ein leichtes Deutsch Problem bin Norweger denoch ist das hier das Beste Forum was ich finden konnte zum Thema. Danke an alle

Habe die Lösung des Problems gefunden es lag tatsächlich an dem. Danke für eure Hilfe





Lg Maik