如何在以下场景中使用Indy的TIdTCPClient
和TIdTCPServer
:
Client ---------- initate connection -----------> Server
...
Client <---------------command------------------- Server
Client ----------------response-----------------> Server
...
Client <---------------command------------------- Server
Client ----------------response-----------------> Server
客户端启动连接,但充当“服务器”(等待命令并执行它们)。
OnExecute
TIdTCPServer
方法在这种情况下效果不佳(至少我没有让它运作良好)。我怎么能这样做?
我希望这个问题很清楚。
答案 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)