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

时间:2011-12-07 12:48:53

标签: delphi client-server delphi-xe indy indy10

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

Client  ---------- initate connection -----------> Server
...
Client  <---------------command------------------- Server
Client  ----------------response-----------------> Server
...
Client  <---------------command------------------- Server
Client  ----------------response-----------------> Server

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

OnExecute TIdTCPServer方法在这种情况下效果不佳(至少我没有让它运作良好)。我怎么能这样做?

我希望这个问题很清楚。

6 个答案:

答案 0 :(得分: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;

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

IdTCPServer1.Bindings.Clear;
IdTCPServer1.Bindings.Add.SetBinding('127.0.0.1', 8080);
IdTCPServer1.Active := True;

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

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

telnet 127.0.0.1 8080

这是输出:

  

你叫什么名字?

     

马库斯

     

你好,马库斯。

     

你想玩游戏吗?

     

与主机丢失的连接。

没有telnet?以下是install telnet client on Vista and 7的方法。

或者使用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;

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

答案 1 :(得分:7)

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

答案 2 :(得分:5)

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

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

希望这有帮助!

答案 3 :(得分:4)

通常客户端和服务器端都有一个线程正在读取传入的报文,并发送待处理的报文......但是这种协议(发送/接收,何时和什么)取决于应用程序。

答案 4 :(得分:3)

一个非常好的起点,如何使用线程实现客户端,从服务器侦听消息,是Indy Telnet客户端组件(Protocols文件夹中的TIdTelnet)。

Indy telnet客户端连接到telnet服务器并使用仅一个套接字来写入读取数据。读取发生在监听器线程中。

这种设计可以很容易地适用于构建分布式消息传递软件,如聊天等,还可以显示使用阻塞套接字将协议与网络层分离是多么容易。

答案 5 :(得分:-3)

对于Indy,这在设计上是不可能的:
Indy仅支持客户端发起的通信,这意味着服务器只能对客户端的请求发送响应 得到你想要的最简单的方法(但不是最聪明)是使用拉动过程。由计时器控制,客户端询问服务器是否有新命令。当然,这会导致大量的流量开销,并且取决于你的拉动间隔,会有延迟 或者,您可以使用其他库,如ICS(http://www.overbyte.be/eng/products/ics.html