2016-08-08 2 views
0

Ich arbeite an einer kleinen Text-basierten Messaging-Plattform über das Netzwerk für meine IT-Klasse.Delphi: Wie kann ich Text an einen bestimmten Client senden, der mit dem Server-Socket verbunden ist und dessen lokale IP-Adresse kennt?

Alles funktioniert, aber jetzt versuche ich eine private Nachricht Funktion zu implementieren, wo Sie im Wesentlichen die IP Ihres Freundes und die Nachricht eingeben, und das wird an den Server gesendet und es ist in der Lage, die Nachricht an den spezifischen Client zu senden zu dieser IP.

Ich habe alles funktioniert, aber ich bin nicht in der Lage, herauszufinden, wie Text an einen bestimmten Client auf der Grundlage ihrer IP-Adresse senden. Ich dachte, ich wäre in der Lage, dies zu tun, wo temp2 ein String ist und msgIP ist die Ziel-IP und msg ist die Botschaft:

for I := 1 to ServerSocket1.Socket.ActiveConnections do 
begin 
    temp2:=ServerSocket1.Socket.Connections[i]; 
    if temp2=msgIP then 
    begin 
    ServerSocket1.Socket.Connections[i].SendText(msg); 
    end; 
end; 

Antwort

5

Es gibt drei Fehler im Code:

  1. Die Connections[] Eigenschaft verwendet 0-basierte Indizes, aber Ihre Schleife verwendet 1-basierte Indizes. Sie werden immer die erste Verbindung überspringen und versuchen, auf die letzte Verbindung zuzugreifen.

  2. Die Connections[]-Eigenschaft gibt einen TCustomWinSocket Objektzeiger zurück, keine Zeichenfolge. Sie müssen die Ziel-IP-Zeichenfolge mit dem Eigenschaftswert des Objekts RemoteAddress vergleichen.

  3. Sie brechen nicht die Schleife, wenn Sie eine Übereinstimmung finden.

Versuchen Sie stattdessen:

var 
    client: TCustomWinSocket; 
begin 
    for I := 0 to ServerSocket1.Socket.ActiveConnections-1 do 
    begin 
    client := ServerSocket1.Socket.Connections[i]; 
    if client.RemoteAddress = msgIP then 
    begin 
     client.SendText(msg); 
     break; 
    end; 
    end; 
end; 

Jetzt, mit dieser sagte, wissen, dass die RemoteAddress ist die Remote-IP-Client aus der Perspektive des Servers. Wenn sich der Client über einen Proxy oder NAT/Router mit dem Server verbindet, ist die IP-Adresse RemoteAddress die des Proxy/NAT, nicht der Client selbst. Mehrere Clients könnten über den gleichen Proxy/NAT verbunden sein, so dass sie alle dieselbe IP-Adresse haben würden: RemoteAddress. Wenn dies nur für eine Klassenzuweisung gilt und kein Proxy/NAT beteiligt ist, kann RemoteAddress in Ordnung sein, vorausgesetzt, Sie haben nicht mehrere Instanzen Ihrer App gleichzeitig auf demselben Computer ausgeführt.

eindeutig einen bestimmten Client auf dem Server, regardlesss von identifizieren, wie es mit dem Server verbunden ist, können Sie die Client-RemoteAddressundRemotePort Eigenschaftswerte zusammen verwenden müssen:

var 
    client: TCustomWinSocket; 
begin 
    for I := 0 to ServerSocket1.Socket.ActiveConnections-1 do 
    begin 
    client := ServerSocket1.Socket.Connections[i]; 
    if (client.RemoteAddress = msgIP) and (client.RemotePort = msgPort) then 
    begin 
     client.SendText(msg); 
     break; 
    end; 
    end; 
end; 

jedoch unter Verwendung von IP + Port ist nicht sehr intuitiv, wenn ein Client mit einem anderen Client kommunizieren möchte, insbesondere wenn er die Port-Werte des anderen nicht kennt.

Eine bessere Option besteht darin, dass sich jeder Client mit einer eindeutigen Kennung, z. B. einem Benutzernamen, beim Server anmeldet. Sie können die TCustomWinSocket.Data Eigenschaft des Clients verwenden, um verfolgen pro-Client-Daten und vergleichen Sie sie je nach Bedarf, zB:

type 
    TClientData = record 
    UserName: string; 
    end; 

... 

// during login... 
var 
    ClientData: TClientData; 
begin 
    New(ClientData); 
    ClientData.UserName := ...; // read from the client 
    Socket.Data := ClientData; 
end; 

... 

// during logout/disconnect... 
var 
    ClientData: TClientData; 
begin 
    ClientData := Socket.Data; 
    Socket.Data := nil; 
    Dispose(ClientData); 
end; 

... 

// during private messaging 
var 
    client: TCustomWinSocket; 
begin 
    for I := 0 to ServerSocket1.Socket.ActiveConnections-1 do 
    begin 
    client := ServerSocket1.Socket.Connections[i]; 
    if TClientData(client.Data).UserName = msgUser then 
    begin 
     client.SendText(msg); 
     break; 
    end; 
    end; 
end; 

Auf diese Weise Sie Nachrichten an einen bestimmten Client senden kann, unabhängig davon, wo er sich befindet und wie es ist mit dem Server verbunden. Vor allem, wenn der Client die Verbindung trennt und wieder herstellt, wobei sich seine IP/Port je Verbindung ändert.Eine Login-ID wäre konsistenter und einfacher zu handhaben.

Verwandte Themen