Подскажите пожалуйста пример работы с lNet

Модератор: Модераторы

Ответить
Freezz
новенький
Сообщения: 10
Зарегистрирован: 13.03.2015 12:23:22

Подскажите пожалуйста пример работы с lNet

Сообщение Freezz »

Добрый день, в примерах к lNet есть проект testnet, в котором показано как работать с компанентами TCP и UDP.
Но там сообщения от сервера получают все клиенты, а как сделать что бы сообщение получал определенный клиент?
Первы раз взялся за клиент серверное приложение, застрял на этом, не пинайте сильно :roll:
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

Почему все? Только тот клиент, который связался с сервером. Вот смотрите:

Код: Выделить всё

Address := ParamStr(1);

Это как раз тот адрес, который Вы задали клиенту для связи с сервером. Соответственно и ответ получит тот же самый клиент, а вовсе не Билл Гейтс. ;-)
На всякий случай - смотрите в каталоге examples/ltcp/. А то вдруг Вы куда-то не в тот пример залезли... :-)
Freezz
новенький
Сообщения: 10
Зарегистрирован: 13.03.2015 12:23:22

Сообщение Freezz »

Vadim, спасибо что ответили.
В данном примере со стороны сервера нет возможности отправлять сообщения на клиенты.
А если отправляешь сообщение с одного клиента, то второй клиент тоже получает это сообщение.
Мне же надо организовать отправку сообщения только на одного из подключившихся клиентов, зная, например, его ip-адрес.
Я смотрел пример examples/visual/tcpudp, там можно отправлять сообщения как с клиентов, так и с сервера, но все рано сообщения получают все...
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

Freezz
Вот смотрите. Сервер просто слушает сеть и ждёт, кто чего ему скажет. Поэтому отправить сообщение можно только на конкретный адрес.
UDP предназначен для быстрого обмена сообщениями, без гарантии их доставки. Поэтому применение udp чревато... Лучше, если нет необходимости обмениваться агромадными объёмами данных, использовать протокол TCP.
Конкретно, в том примере, который Вы указали, применяется функция SendToAll() - название говорит само за себя ;-) сами понимаете, ничего другого, как посылка сообщений всей округе ждать от этой функции нечего. Данная функция как раз и заведует тем, чтобы никто не ушёл несообщённым. ;-) Для этого используется специальный широковещательной маской сети, которая в примере представлена константой LADDR_BR и является на самом деле вот этим: 255.255.255.255.
Именно по этой причине и на основании Вашего вопроса, я предложил Вам другой пример, который отвечает поставленной Вами задаче. Не смотрите, что это пример для консоли. Связь и обмен сообщениями сервера с клиентом не имеют никакого отношения ни к окнам ни к консоли. Хотите окошки - вставляете код классов в свои окошки и вперёд... ;-)
Freezz
новенький
Сообщения: 10
Зарегистрирован: 13.03.2015 12:23:22

Сообщение Freezz »

Vadim, у меня в голове полная каша образовалась пока я эти примеры рассматривал :shock:
Я наверное, просто непонятно вопрос задаю...
Давайте так, вот этот кусочек программы, перебирая всех подключенных клиентов, отправляет им сообщение. Всем.

Код: Выделить всё

FNet.IterReset; // start at server socket
while FNet.IterNext do begin // skip server socket, go to clients only
  n := FNet.SendMessage(aMsg, FNet.Iterator);
  if n < Length(aMsg) then
    MemoText.Append('Error on send [' + IntToStr(n) + ']');
end;

Мне же надо выбрать одного из клиентов и передать ему сообщение.
Я так понимаю надо в строке n := FNet.SendMessage(aMsg, FNet.Iterator); вместо FNet.Iterator подставить указание на конкретного клиента, соответственно убрав цикл while do.
Так вот ЧТО именно надо написать, зная ip-адрес клиента?
Спасибо за терпение, первый раз пытаюсь написать подобное приложение. Про lNet в интернете что-то ничего внятного не нашел, поэтому и решил на форуме вопрос задать.
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

У lnet примеры довольно понятные, наверно поэтому и документации подробной нет.
В методе SendMessage(aMsg, FNet.Iterator), параметр FNet.Iterator - это сокет, который содержит в себе адрес того, кому направляется сообщение. Следовательно нужно этот адрес узнавать во время пробежки по списку сокетов-клиентов и если нашёлся подходящий - слать ему сообщение. В общем случае должно быть что-то вроде:

Код: Выделить всё

while FNet.IterNext do 
  If FNet.Iterator.LocalAddress='192.168.0.12' Then //адрес взят с потолка ;-)
  Begin
    FNet.SendMessage(aMsg, FNet.Iterator);
    Exit;  //Выходим из цикла, он нам больше не нужен
  End;
 

Или так, если Вы знаете, под каким номером в списке сидит клиент:

Код: Выделить всё

Var
  mySock: TLSocket;
Begin
  mySock:=FNet.Socks[Номер_клиента_по_списку_начиная_с_нуля];
  mySock.SendMessage(aMsg);
End;
Freezz
новенький
Сообщения: 10
Зарегистрирован: 13.03.2015 12:23:22

Сообщение Freezz »

Vadim, огромное спасибо! То что нужно было! Первый вариант отлично подойдет.
Freezz
новенький
Сообщения: 10
Зарегистрирован: 13.03.2015 12:23:22

Сообщение Freezz »

Уважаемый Vadim, а можно ли в lNet открыть для прослушивания два порта?
Попробовал сделать так:

Код: Выделить всё

procedure TLTCPrmtserver.Run;
var
  quit: Boolean;
  s: String;
  c: Char;
begin
  quit := false;
  s := '';                       
  FNet.Listen(1305);
  FNet.Listen(1501);
  Writeln('Сервер запущен');
  Writeln('''Escape'' - выход');
  repeat
    FNet.CallAction;
    if KeyPressed then begin
      c := ReadKey;
      case c of
        #27: quit := true;
        #8: begin
          if Length(s) > 1 then Delete(s, Length(s) - 1, 1)
          else s := '';
          GotoXY(WhereX - 1, WhereY);
          Write(' ');
          GotoXY(WhereX - 1, WhereY);
        end;
        #10,
        #13: begin
          FNet.SendMessage(s);
          s := '';
          Writeln;
        end;
        else begin
          s := s + c;
          Write(c);
        end;
      end;
    end;
  until quit;
end;           

открывается только один порт, и почему-то второй из списка (в данном случае 1501).
И, кстати, FNet.aSocket.PeerPort всегда выдает ноль почему-то :(
хотя FNet.aSocket.PeerAddress правильно выдает адрес подсоединившегося клиента.
Аватара пользователя
Снег Север
долгожитель
Сообщения: 3069
Зарегистрирован: 27.11.2007 15:14:47
Контактная информация:

Сообщение Снег Север »

Не скажу конкретно про lNet, но как правило, для двух портов надо иметь два разных экземпляра компонента. У вас же в коде всё логично - вы переопределяете вторым вызовом порт для прослушивания и прослушивается только он.
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

Freezz
Действительно, Снег Север совершенно прав - каждый созданный экземпляр объекта может прослушивать только один порт.
Freezz
новенький
Сообщения: 10
Зарегистрирован: 13.03.2015 12:23:22

Сообщение Freezz »

Снег Север, Vadim спасибо вам, ведь действительно ответ лежал на поверхности. Надо сделать перерыв, скушать твикс :D
Ответить