Indy TCP客户端/服务器,客户端充当服务器

jpf*_*ius 18 delphi client-server indy indy10 delphi-xe

如何使用Indy TIdTCPClientTIdTCPServer在以下场景中使用:

Client  ---------- initate connection -----------> Server
...
Client  <---------------command------------------- Server
Client  ----------------response-----------------> Server
...
Client  <---------------command------------------- Server
Client  ----------------response-----------------> Server
Run Code Online (Sandbox Code Playgroud)

客户端启动连接,但充当"服务器"(等待命令并执行它们).

OnExecute的方法TIdTCPServer并不在此情况下(至少我没有得到它的工作好)很好地工作.我怎么能这样做?

我希望这个问题足够清楚.

Mar*_*ams 18

没有什么能阻止你使用Indy的TIdTCPServer组件.

TIdTCPServer仅设置连接.你需要实现其余的.因此,实际发送和接收的顺序可以是您想要的任何内容.

将此代码放在TIdTCPServer组件的OnExecute事件中:

var
  sName: String;
begin
  // Send command to client immediately after connection
  AContext.Connection.Socket.WriteLn('What is your name?');
  // Receive response from client
  sName := AContext.Connection.Socket.ReadLn;
  // Send a response to the client
  AContext.Connection.Socket.WriteLn('Hello, ' + sName + '.');
  AContext.Connection.Socket.WriteLn('Would you like to play a game?');
  // We're done with our session
  AContext.Connection.Disconnect;
end;
Run Code Online (Sandbox Code Playgroud)

以下是如何简单地设置TIdTCPServer的方法:

IdTCPServer1.Bindings.Clear;
IdTCPServer1.Bindings.Add.SetBinding('127.0.0.1', 8080);
IdTCPServer1.Active := True;
Run Code Online (Sandbox Code Playgroud)

这告诉服务器仅在端口8080上侦听环回地址.这可以防止计算机外的任何人连接到它.

然后,要连接客户端,可以转到Windows命令提示符并键入以下内容:

telnet 127.0.0.1 8080
Run Code Online (Sandbox Code Playgroud)

这是输出:

你叫什么名字?

马库斯

你好,马库斯.

你想玩游戏吗?

与主机的连接丢失.

没有telnet?以下是在Vista和7上安装telnet客户端的方法.

或者使用TIdTCP客户端,您可以执行以下操作:

var
  sPrompt: String;
  sResponse: String;
begin
  // Set port to connect to
  IdTCPClient1.Port := 8080;
  // Set host to connect to
  IdTCPClient1.Host := '127.0.0.1';
  // Now actually connect
  IdTCPClient1.Connect;
  // Read the prompt text from the server
  sPrompt := IdTCPClient1.Socket.ReadLn;
  // Show it to the user and ask the user to respond
  sResponse := InputBox('Prompt', sPrompt, '');
  // Send user's response back to server
  IdTCPClient1.Socket.WriteLn(sResponse);
  // Show the user the server's final message
  ShowMessage(IdTCPClient1.Socket.AllData);
end;
Run Code Online (Sandbox Code Playgroud)

这里要注意的一件重要事情是ReadLn语句一直等到有数据.这就是背后的魔力.

  • 应该将'magic'放在自己的线程中,以便应用程序可以在服务器无话可说时继续 (7认同)

Rem*_*eau 7

如果您的命令本质上是文本的,那么请查看该TIdCmdTCPClient组件,它专门针对服务器发送命令而不是客户端的情况而设计.服务器可以使用TIdContext.Connection.IOHandler.WriteLn()TIdContext.Connection.IOHandler.SendCmd()发送命令.


LaK*_*ven 5

当客户端连接到服务器时,服务器具有带AContext: TIdContext参数的OnConnect事件.

这是一个属性AContext.Connection,您可以在该事件之外存储(例如,在数组中).如果您将其与IP或更好的生成的会话ID配对,然后按该条件引用该连接,则可以让服务器向客户端发送adhoc命令或消息.

希望这可以帮助!

  • 是的,这个解决方案允许这样做!服务器只需要存储每个客户端的连接,以便它可以直接将消息或命令传递给一个或多个客户端,而不必首先响应客户端命令! (2认同)
  • 客户端与服务器有持久连接,所以当然它在客户端有一个监听线程;)应该指出我实际上已经(反复)实现了双向通信的客户端/服务器系统. (2认同)