我正在通过网络为我的IT班工作一个基于文本的小型消息传递平台。
一切正常,但现在我尝试实现一个私人消息功能,您实际上输入了朋友的IP和消息,并将其发送到服务器并且能够发送消息与该IP相关的特定客户。
我有一切正常,除了我无法弄清楚如何根据IP地址向一个特定客户发送文本。我认为如果temp2
是字符串并且msgIP
是目标IP并且msg
是消息,我将能够这样做:
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;
答案 0 :(得分:5)
您的代码中有三个错误:
Connections[]
属性使用从0开始的索引,但您的循环使用的是基于1的索引。您将始终跳过第一个连接,并在尝试访问最后一个连接时崩溃。
Connections[]
属性返回TCustomWinSocket
对象指针,而不是字符串。您需要将目标IP字符串与对象的RemoteAddress
属性值进行比较。
如果找到匹配项,您不会破坏循环。
请改为尝试:
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;
现在,据说,从服务器的角度来看,知道RemoteAddress
是远程客户端的IP。如果客户端通过代理或NAT /路由器连接到服务器,则RemoteAddress
IP将是代理/ NAT的IP,而不是客户端本身。可以通过相同的代理/ NAT连接多个客户端,因此它们都具有相同的RemoteAddress
IP。如果这仅适用于课程作业且不涉及代理/ NAT,那么RemoteAddress
可能没问题,只要您不在同一台计算机上同时运行多个应用实例。
要唯一标识服务器上的特定客户端,无论其如何连接到服务器,您都需要使用客户端RemoteAddress
和 {{1} }属性值在一起:
RemotePort
然而,当一个客户希望与另一个客户通信时,使用IP +端口并不是非常直观,特别是如果他们不了解彼此的端口值。
更好的选择是让每个客户端使用唯一标识符(例如用户名)登录服务器。您可以使用客户端的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;
属性来跟踪每个客户端数据并根据需要进行比较,例如:
TCustomWinSocket.Data
这样,您可以将消息发送到特定客户端,无论其位于何处以及如何连接到服务器。特别是如果客户端断开连接并重新连接,其IP /端口每个连接都会更改。登录标识符将更加一致且更易于使用。