Indy TCP Client / Server с клиентом, действующим как сервер - PullRequest
18 голосов
/ 07 декабря 2011

Как можно использовать Indy's TIdTCPClient и TIdTCPServer в следующем сценарии:

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

Клиент инициирует соединение , но действует как "сервер" (ожидание команд и их выполнение).

Подход OnExecute к TIdTCPServer не работает в этом случае (по крайней мере, я не могу заставить его работать) Как я мог это сделать?

Надеюсь, вопрос достаточно ясен.

Ответы [ 6 ]

18 голосов
/ 07 декабря 2011

Ничто не мешает вам сделать это с компонентом Indy TIdTCPServer.

TIdTCPServer только устанавливает соединение.Вам нужно будет реализовать все остальное.Таким образом, последовательность фактической отправки и получения может быть любой, что вы хотите.

Поместите этот код в событие OnExecute вашего компонента TIdTCPServer:

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 в Vista и 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 ждут, пока не появятся данные.В этом вся магия.

7 голосов
/ 07 декабря 2011

Если ваши команды имеют текстовый характер, обратите внимание на компонент TIdCmdTCPClient, он специально разработан для ситуаций, когда сервер отправляет команды вместо клиента.Сервер может использовать TIdContext.Connection.IOHandler.WriteLn() или TIdContext.Connection.IOHandler.SendCmd() для отправки команд.

5 голосов
/ 07 декабря 2011

Когда клиент подключается к серверу, на сервере происходит событие OnConnect с параметром AContext: TIdContext.

Это свойство AContext.Connection, которое вы можете хранить вне этого события (скажем, в массиве). Если вы связываете его с IP-адресом или, что еще лучше, сгенерированным идентификатором сеанса, а затем ссылаетесь на это соединение по этим критериям, вы можете заставить сервер отправлять команды или сообщения adhoc клиенту.

Надеюсь, это поможет!

4 голосов
/ 07 декабря 2011

обычно клиент и сторона сервера имеют поток, который читает входящие телеграммы и отправляет ожидающие телеграммы ... но этот тип протоколов (отправка / получение, когда и что) зависит от приложения.

3 голосов
/ 07 декабря 2011

Очень хорошей отправной точкой для реализации клиентской части с помощью потока, прослушивающего сообщения с сервера, является клиентский компонент Indy Telnet (TIdTelnet в папке Protocols).

Клиент Telnet Indy подключается к серверу telnet и использует только один сокет для записи и чтения данных. Чтение происходит в потоке слушателя.

Эта схема может быть легко адаптирована для создания распределенного программного обеспечения для обмена сообщениями, такого как чат и т. Д., А также показывает, насколько легко можно отделить протокол от сетевого уровня с помощью блокирующих сокетов.

0 голосов
/ 07 декабря 2011

С Indy это невозможно по замыслу:
Indy поддерживает только инициированную клиентом связь, что означает, что сервер может только отправлять ответ на запросы клиента.
Самый простой способ (но не самый умный), чтобы получить то, что вы хотите, это использовать процесс извлечения. Управляемые таймером клиенты спрашивают сервер, есть ли новая команда. Конечно, это вызовет много трафика, и в зависимости от вашего интервала доступа будет задержка.
В качестве альтернативы вы можете использовать другую библиотеку, такую ​​как ICS (http://www.overbyte.be/eng/products/ics.html)

...