簡體   English   中英

Indy TCP客戶端/服務器,其中客戶端充當服務器

[英]Indy TCP Client/Server with the client acting as a server

在以下情況下如何使用Indy的TIdTCPClientTIdTCPServer

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

客戶端啟動連接 ,但充當“服務器”(等待命令並執行它們)。

在這種情況下, TIdTCPServerOnExecute方法不能很好地工作(至少我無法使其正常工作)。 我該怎么辦?

我希望這個問題足夠清楚。

沒有什么可以阻止您使用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

這是輸出:

你叫什么名字?

馬庫斯

哈Mar,馬庫斯

你想玩游戲嗎?

與主機的連接丟失。

沒有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;

這里要注意的重要一點是ReadLn語句要等到有數據時才開始。 這就是這一切的魔力。

如果您的命令本質上是文本命令,那么請看一下TIdCmdTCPClient組件,該組件專門用於服務器發送命令而不是客戶端發送命令的情況。 服務器可以使用TIdContext.Connection.IOHandler.WriteLn()TIdContext.Connection.IOHandler.SendCmd()發送命令。

當客戶端連接到服務器時,服務器將發生帶有AContext: TIdContext參數的OnConnect事件。

它的一個屬性是AContext.Connection ,您可以將其存儲在該事件之外(例如,存儲在Array中)。 如果將其與IP或更佳的會話ID配對,然后根據該標准引用該Connection,則可以讓服務器將臨時命令或消息發送給客戶端。

希望這可以幫助!

通常,客戶端和服務器端都有一個線程,該線程正在讀取傳入的電報,並發送未決的電報...但是這種協議(發送/接收,何時何地)取決於應用程序。

Indy Telnet客戶端組件(Protocols文件夾中的TIdTelnet)是一個非常好的起點,可以使用線程來實現客戶端偵聽來自服務器的消息。

Indy telnet客戶端連接到telnet服務器,並且使用一個套接字來寫入讀取數據。 讀取發生在偵聽器線程中。

這種設計可以輕松地用於構建諸如聊天等類似的分布式消息傳遞軟件,並且還顯示了使用阻塞套接字將協議與網絡層分離的容易程度。

使用Indy,這在設計上是不可能的:
Indy僅支持客戶端發起的通信,這意味着服務器只能發送對客戶端請求的響應。
獲得所需內容的最簡單方法(但不是最聰明的方法)是使用拉動過程。 客戶端通過計時器控制,詢問服務器是否有新命令。 當然,這將導致大量的流量開銷,並且取決於您的拉間隔,會有延遲。
或者,您可以使用另一個類似ICS的庫( http://www.overbyte.be/eng/products/ics.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM