Конференция "Сети" » Свой протокол [D7, WinXP]
 
  • OrdJONY © (24.08.07 21:22) [0]
    Приветствую всех на этом форуме. Появилась идея сделать что-то подобное протоколу аськи. Тоесть написать сервак и клиент естесно)).
    Столкнулся с множеством проблем, хочу написать на Indy. Хотелось бы увидеть простенький пример взаимодействия TIdTCPServer и TIdTCPClient:
    Login <Name User> <Password>;{Это авторизация, после успешной авторизации, данному юзеру отправляется сообщение LoginOK, а остальным UserOnline}
    SendMessage <Name User> <Text Msg>; {Имя Юзера и текст сообщения посылается на серв, а потом после обработки должно прийти второму юзеру командой incomingMessage}
    Disconect; {С этим все понятно и какой ответ будет на это сообщение}
    Это команды на сервере, а вот команды на клиенте:
    LoginOK; {Это когда принят логин и пароль ответ сервера}
    UserOnline <Name User>; {Когда Юзер входит в сеть}
    incomingMessage <Name User> <Text Msg>; {Пришло сообщение, тут видимо разделители нужно использовать не пробелы, чтобы сообщение он нормально в параметры загнал}
    +На компе юзера может запускатся несколько клиентов, как сделать чтобы сообщение клиенту отправлялось не на IP а именно на Thread, тоесть данное подключение.
  • grisme © (26.08.07 19:56) [1]

    > +На компе юзера может запускатся несколько клиентов, как
    > сделать чтобы сообщение клиенту отправлялось не на IP а
    > именно на Thread, тоесть данное подключение.


    ну что ты, что ты :) "так" и будет.
  • Сергей М. © (27.08.07 08:48) [2]

    > хочу написать на Indy. Хотелось бы увидеть простенький пример
    > взаимодействия TIdTCPServer и TIdTCPClient


    http://www.indyproject.org/Sockets/Demos/index.EN.aspx


    > сообщение клиенту отправлялось не на IP а именно на Thread


    В 9-ке в обработчике OnExecute:

    PeerThread.Connection.SendXXX
  • OrdJONY © (28.08.07 00:18) [3]

    > В 9-ке в обработчике OnExecute:PeerThread.Connection.SendXXX

    а если сообщение нужно отправить не по обработчику OnExecute, а вот что-то произошло на сервере и нужно юзеру отправить это???
  • Сергей М. © (28.08.07 08:25) [4]
    Тогда поток, ответственный за контроль над "что-то произошло на сервере", должен тем или иным образом известить PeerThread юзера о том, что "это" следует отправить юзеру.
  • DVM © (28.08.07 23:12) [5]

    > хочу написать на Indy. Хотелось бы увидеть простенький пример
    > взаимодействия TIdTCPServer и TIdTCPClient:

    Не лучший имхо вариант.
  • DiamondShark © (03.09.07 14:23) [6]
    Я всегда говорил, что компоненты поверх WinSock -- это искусственная сложность.
  • Сергей М. © (03.09.07 14:40) [7]

    > DiamondShark ©   (03.09.07 14:23) [6]


    Вот ведь беда !

    Как же это Борланд и прочие разработчики забыли у тебя спросить ?)
  • OrdJONY © (25.09.07 14:27) [8]
    Расскажите как собирать пакет, а потом его читать. Заголовок у пакета всегда должен быть фиксированной длинны 8 байт. VerProto (1 Байт, принимает значение от 1, 2, 3, 4...), NumCmd (2 байта, сдесь случайное число), IDService (1 байт, аналогично VerProto), SizeData (4 байта, размер данных); Далее следуют данные, размер их указывает в заголовке в SizeData. Это все надо собрать в один пакет и отослать. На приемнике нужно разобрать сначала зоголовок, а потом вытянуть из сокета SizeData байт.
    Помогите, кто чем может ))
  • DVM © (25.09.07 14:49) [9]

    > Это все надо собрать в один пакет и отослать.

    пакеты тут не при чем. Собирай все в буфер array[0..xx] of byte и отсылай его. Причем желательно чтобы начало и конец буфера были как то помечены, чтобы знать, что получены полные данные.
  • Сергей М. © (25.09.07 15:44) [10]

    > желательно чтобы начало и конец буфера были как то помечены,
    >  чтобы знать, что получены полные данные


    Совершенно лишнее это.

    На транспортном уровне доставка потока гарантирована в оригинальной последовательности, а на прикладном уровне инф-ция о данных переменного размера, следующих за заголовком, фигурирует в самом заголовке фикс.размера. "Промахнуться" с приемом "пакета" в таких условиях практически невозможно. Для самоуспокоения и пущей уверенности можно в заголовке предусмотреть поля ид-ра сессии и контрольной суммы.
  • DVM © (25.09.07 16:01) [11]

    > Совершенно лишнее это.

    Я думаю все же не лишнее. Например, не исключена ситуация, когда клиент подключится не к своему родному серверу а еще к чему то там. И этот левый сервер вышлет какой то набор байт, который клиент примет. Но этот набор байт будет содержать некорректную информацию. Если же начло и конец буфера будут помечены (например как у JPEG FFD8 FFD9), то это в какой то степени повысит вероятность того, что принятый нами блок данных это данные нашего формата, а не что то постороннее.
  • Сергей М. © (25.09.07 16:08) [12]

    > DVM ©   (25.09.07 16:01) [11]


    На и нужны поля ид-ра сессии и контр.суммы.

    Вероятность их подделки ничтожна мала, а уж случайного совпадения и подавно. Если бы было иначе, то, к примеру, аськина сеть давным-давно бы перестала существовать как ненадежная в плане безопасности.
  • DVM © (25.09.07 16:16) [13]

    > На и нужны поля ид-ра сессии и контр.суммы.

    Ну или так. Я правда не о безопасности толкую, а о том чтобы потом в принимаемом потоке данных блоки команд удобно было бы выделять по этим разделителям. Особенно если эти блоки не имеют фиксированного размера.
    Ведь при пересылке может получиться что в приемном буфере после очередной операции чтения окажется первая команда и половина второй. Вот чтобы первую отделить метки и понадобятся.
  • Сергей М. © (25.09.07 16:30) [14]

    > при пересылке может получиться что в приемном буфере после
    > очередной операции чтения окажется первая команда и половина
    > второй. Вот чтобы первую отделить метки и понадобятся


    А нафих читать пол-второй команды, если к первой она не относится ?)

    Метки те самые нужны только тогда, когда протокол не предусматривает никакой инф-ции о полном размере инф.сообщений. Но это не случай автора.
  • OrdJONY © (25.09.07 16:58) [15]
    напишите плиз такой примерчик. А то вот читаю и пока собственно непонял как реализовать мною написанное ))
  • DVM © (25.09.07 17:02) [16]

    > А нафих читать пол-второй команды, если к первой она не
    > относится ?)

    Ну а как мы узнаем, что первая команда то кончилась? Мы читаем, читаем, когда остановиться то? Мы допустим не знаем длину очередной команды.

    > Но это не случай автора.

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

    COMMAND: MESSAGE FROM: VASYA TO: PETYA MESSAGETEXT: BLA-BLA-BLA

    вот размер этих BLA-BLA-BLA нам и неизвестен. Т.е. когда остановиться мы не знаем. Поэтому либо поле размер надо ввести, либо разделитель, а лучше и то и другое.
  • DVM © (25.09.07 17:03) [17]

    > напишите плиз такой примерчик.

    тут не примерчик а примерище огромный.
  • DVM © (25.09.07 17:05) [18]

    > напишите плиз такой примерчик.

    одна тема логина на сервер чего стоит, если безопасную проверку пароля организовать, т.е не пересылать пароль в открытом виде.
  • Сергей М. © (25.09.07 17:19) [19]

    > Мы читаем, читаем, когда остановиться то?


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


    > Мы допустим не знаем длину очередной команды


    Тогда те самые метки и нужны. Но, повторяю, это не случай автора, в его случае на принимающей стороне в каждый момент времени известно, сколько "весит" очередной принимаемый пакет.
  • umbra © (25.09.07 17:23) [20]
    для упрощения подобных изобретений в инди 9 у
    TIdTCPServer

    есть коллекция
    CommandHanlers

    , а в инди 10 - отдельный компонент
    TIdCmdTCPServer

    .
  • OrdJONY © (25.09.07 19:50) [21]

    > одна тема логина на сервер чего стоит, если безопасную проверку
    > пароля организовать, т.е не пересылать пароль в открытом
    > виде.

    Да не надо мне безопасная проверка пароля. Напишите простенький пример, как собрать такой пакет, а потом прочитать его. Пример относится только к пакету
  • DVM © (25.09.07 21:39) [22]

    > а потом прочитать его

    Тебе через инди что ли? Ну вот совсем примитивно:


    procedure TfrmMain.btnSendTCPCommandClick(Sender: TObject);
    var
     SendBuff: array[1..14] of byte;
     RecvBuff: array[1..12] of byte;
     res: string;
     i: integer;
    begin
     IdTCPClient.Host := edtHost.Text;
     IdTCPClient.Port := spnedtPort.Value;
     try
       IdTCPClient.Connect;
     except
       // ошибка
     end;
     
     SendBuff[1] := $6;
     SendBuff[2] := $2;
     SendBuff[3] := $0;
     SendBuff[4] := $A;
     SendBuff[5] := $0;
     SendBuff[6] := $3;
     SendBuff[7] := $1;
     .....
     .....
     .....

     if IdTCPClient.Connected then
       begin
         IdTCPClient.WriteBuffer(SendBuff, SizeOf(SendBuff), true);
         IdTCPClient.ReadBuffer(RecvBuff, SizeOf(RecvBuff));
       end;

     IF IdTCPClient.Connected then IdTCPClient.Disconnect;
    end;

  • OrdJONY © (25.09.07 23:17) [23]

    >   SendBuff[1] := $6;  SendBuff[2] := $2;  SendBuff[3] :=
    > $0;  SendBuff[4] := $A;  SendBuff[5] := $0;  SendBuff[6]
    > := $3;  SendBuff[7] := $1;

    а что это за значения??? Разъясните пожалуйста
  • DVM © (25.09.07 23:19) [24]

    > а что это за значения??? Разъясните пожалуйста

    Это от балды взятые числа. Ты туда свои пиши.
  • OrdJONY © (26.09.07 10:21) [25]
    Спасибо вам за помощь DVM!!!
 
Конференция "Сети" » Свой протокол [D7, WinXP]
Есть новые Нет новых   [134431   +10][b:0][p:0.002]