Роботы, плагины и скрипты к чату MyChat. Разработка альтернативных клиентов и различных утилит. Технические вопросы по программированию, замечания и предложения по развитию API
Аватара пользователя
SV
Решил опробовать подключиться ботом к серверу.
Код: Выделить всё
const CRLF                 = '#13#10';
     MagicString           = '#23#6';
     cs_hello              = '0001';
     cs_login              = '0003';
     SendingFlags          = '00';

  IdTCPClient1.Connect;
  IdTCPClient1.Socket.WriteLn('mc5.0' + CRLF + '{"Secured":""}');

Всё хорошо получаем ответ:
Код: Выделить всё
800000{"ServPass":false,"ServName":"ILYA","UpdatePacketVer":"","UTC":4,"RelDate":"15.07.2014","ProtocolVer":"2.5","PortNode":80,"PortHTTP":8083,"PortFTP":20000,"ServerVer":"5.6.0","Registered":"-","HelloMsg":"Welcome to -=MyChat=- Server\r\nCopyright (c) 2004-2013 by Alexey Pikurov \/ Network Software Solutions\r\nWWW: https:\/\/nsoft-s.com\r\nE-Mail: [email protected]\r\nSupport https:\/\/nsoft-s.com\/forum\r\nBlog: http:\/\/blog.nsoft-s.com","UpdatePacketSize":1,"YourIP":"192.168.1.5","HWID":"284979801_0_6-5-5-516875208","Free":false,"ForceUpdate":true,"CurrentDT":"20.08.2014.16.59.42.154"}

Идём дальше отправляем ему в ответ:
Код: Выделить всё
function my_hello:WideString;
var
  JSONobj: ISuperObject;
  JsonArray: TSuperArray;
begin
  JSONobj := SO();
  JSONobj.S['ProtocolVer']  := '2.5';
  JSONobj.S['Client']       := 'win32';
  JSONobj.B['Packed']       := false;
  JSONobj.S['ServPass']     := '';
  JSONobj.S['MAC']          := '00-17-31-57-6C-61';
  JSONobj.S['HardwareID']   := '45678906546';
  JSONobj.S['NetName']      := 'COMPOFFICE';
  JSONobj.S['Ver']          := '5.6.0';
  JSONobj.S['OS']           := 'Windows 7';
  JSONobj.S['Secured']      := '';
  JSONobj.I['UTC']          := 4;
  JSONobj.O['Interfaces']   := SA([]);
  JSONobj.A['Interfaces'].S[0]:= '192.168.1.5';

  result := JSONobj.AsJSon;
  JSONobj.Clear(true);
  JSONobj := nil;
end;

  IdTCPClient1.Socket.WriteLn(MagicString + cs_hello + SendingFlags + my_hello + CRLF);

  Memo1.Lines.Add(IdTCPClient1.Socket.ReadLn);

И тут молчание.

Полный код:
Код: Выделить всё
const CRLF                 = '#13#10';
     MagicString           = '#23#6';
     cs_hello              = '0001';
     cs_login              = '0003';
     SendingFlags          = '00';


function my_hello:WideString;
var
  JSONobj: ISuperObject;
  JsonArray: TSuperArray;
begin
  JSONobj := SO();
  JSONobj.S['ProtocolVer']  := '2.5';
  JSONobj.S['Client']       := 'win32';
  JSONobj.B['Packed']       := false;
  JSONobj.S['ServPass']     := '';
  JSONobj.S['MAC']          := '00-17-31-57-6C-61';
  JSONobj.S['HardwareID']   := '45678906546';
  JSONobj.S['NetName']      := 'COMPOFFICE';
  JSONobj.S['Ver']          := '5.6.0';
  JSONobj.S['OS']           := 'Windows 7';
  JSONobj.S['Secured']      := '';
  JSONobj.I['UTC']          := 4;
  JSONobj.O['Interfaces']   := SA([]);
  JSONobj.A['Interfaces'].S[0]:= '192.168.1.5';

  result := JSONobj.AsJSon;
  JSONobj.Clear(true);
  JSONobj := nil;
end;



procedure TForm1.Button1Click(Sender: TObject);
begin
  IdTCPClient1.Connect;
  IdTCPClient1.Socket.WriteLn('mc5.0' + CRLF + '{"Secured":""}');

  IdTCPClient1.Socket.WriteLn(MagicString + cs_hello + SendingFlags + my_hello + CRLF);

  Memo1.Lines.Add(IdTCPClient1.Socket.ReadLn);


end;


Что не так?
Аватара пользователя
Алексей Пикуров
Поменяйте местами
IdTCPClient1.Socket.WriteLn(MagicString + cs_hello + SendingFlags + my_hello + CRLF);
и
Memo1.Lines.Add(IdTCPClient1.Socket.ReadLn);

В протоколе сказано:
1. Клиент открывает соединение с сервером по TCP на указанный порт (по умолчанию 2004) и отправляет на сервер текстовую строку-сигнатуру "mc5.0" (без двойных кавычек) + CRLF.
"mc" - сигнатура программы, "5.0" - версия протокола обмена данными.
2. Клиент отправляет на сервер команду {"Secured":"SSL"} + CRLF, если он собирается использовать шифрование трафика, или {"Secured":""} + CRLF - если шифрование не нужно.
3. Сервер шлёт клиенту в ответ команду sc_hello
4. Клиент проверяет, может ли он подключаться к серверу, и шлёт ему в ответ команду cs_hello

т.е. перед тем, как отправлять cs_hello, надо сначала прочитать ответ от сервера.

Дальше - сигнатура версии сейчас - mc5.6 (версия-то 5.6).

ProtocolVer - 2.5

Поменяйте и попробуйте ещё раз.
Аватара пользователя
SV
Код: Выделить всё
function my_hello:WideString;
var
  JSONobj: ISuperObject;
  JsonArray: TSuperArray;
begin
  JSONobj := SO();
  JSONobj.S['ProtocolVer']  := '2.5';
  JSONobj.S['Client']       := 'win32';
  JSONobj.B['Packed']       := false;
  JSONobj.S['ServPass']     := '';
  JSONobj.S['MAC']          := '00-17-31-57-6C-61';
  JSONobj.S['HardwareID']   := '45678906546';
  JSONobj.S['NetName']      := 'COMPOFFICE';
  JSONobj.S['Ver']          := '5.6';
  JSONobj.S['OS']           := 'Windows 7';
  JSONobj.S['Secured']      := '';
  JSONobj.I['UTC']          := 3;
  JSONobj.O['Interfaces']   := SA([]);
  JSONobj.A['Interfaces'].S[0]:= '192.168.1.5';

  result := JSONobj.AsJSon;
  JSONobj.Clear(true);
  JSONobj := nil;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  IdTCPClient1.Connect;

   IdTCPClient1.Socket.WriteLn('mc5.6' + CRLF + '{"Secured":""}');
   Memo1.Lines.Add(IdTCPClient1.Socket.ReadLn);
   IdTCPClient1.Socket.WriteLn(MagicString + cs_hello + SendingFlags + my_hello + CRLF);
end;


Так?
Аватара пользователя
Алексей Пикуров
Вроде да.
Аватара пользователя
Алексей Пикуров
Вот, что должно отправляться в ответ серверу, как пример.
#23#6 000100{"ServPass":"","Client":"win32","Ver":"5.6.0","UTC":3,"MAC":"36-EC-99-CB-1C-C5","ProtocolVer":"2.5","NetName":"TOSHIBA-PC","Packed":false,"OS":"Windows XP","Secured":"","Interfaces":["192.168.1.103","192.168.56.1"],"HardwareID":"6-10-9-630356458"}

Это мой пример, "живой".
Аватара пользователя
SV
А как же в конце:
Код: Выделить всё
CRLF = '#13#10';
?
Аватара пользователя
Алексей Пикуров
CRLF в конце - стандартно, после каждой команды.
Аватара пользователя
Алексей Пикуров
В вашем исходнике несколько ошибок.

1. Вы используете Indy, метод IdTCPClient1.Socket.WriteLn
Он сам добавляет в конец строки CRLF, поэтому "доклеивать" его не нужно.

2. В описании констант у вас написано:
Код: Выделить всё
const CRLF                 = '#13#10';
     MagicString           = '#23#6';

Это неверно, вы объявили строки, как последовательности символов (6 символов и 5, соответственно, а должно быть 2 и 2). Правильно так:
Код: Выделить всё
const CRLF                 = #13#10;
     MagicString           = #23#6;
Аватара пользователя
SV
Понятно, константы команд, указывать тоже без ковычек?
Аватара пользователя
Алексей Пикуров
Команды в кавычках, там последовательности текстовые по 4 байта, ASCII.
Аватара пользователя
SV
Спасибо за помощь. Теперь понял как работать.