Es gibt drei Fehler im Code:
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.
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.
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-RemoteAddress
undRemotePort
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.