Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Компоненты Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 04.01.2011, 20:57   #1
Adamrus
Пользователь
 
Аватар для Adamrus
 
Регистрация: 26.11.2009
Сообщений: 59
По умолчанию Indy10

Здравствуйте.
Разъясните, пожалуйста, как в 10 версии Indy через TCPServer и TCPClient передавать тип данных record?
в предыдущих версиях я делал так:
клиент писал: IdTCPClient1.WriteBuffer (NewCommBlock, SizeOf (CommBlock), true);
сервер встречал: AThread.Connection.ReadBuffer (CommBlock, SizeOf (CommBlock));
CommBlock - record, с кучей полей, ником, номером игры, координатами и т.д.

вот сетевая игра, к-ю я писал на предыдущей версии Indy. Кстати, если кому поможет, буду рад, отказоустойчивая сетевая игра "Крестики нолики", сервер держит 3 игры, соот-но макс.кол-во игроков 6, если падает сервер, то клиенты ищут другой доступный сервер.
Вложения
Тип файла: rar net_game.rar (427.5 Кб, 45 просмотров)

Последний раз редактировалось Adamrus; 04.01.2011 в 21:31.
Adamrus вне форума Ответить с цитированием
Старый 05.01.2011, 00:58   #2
Adamrus
Пользователь
 
Аватар для Adamrus
 
Регистрация: 26.11.2009
Сообщений: 59
По умолчанию

Код:
type TDataBlock = record
  cmd: Integer;
  nick,
  msg: ShortString;
end;
В общем так (нашел на одном буржуйском сайте):
1) подключаем IdGlobal в Uses, иначе RawToBytes (и обратно) не определена
2) клиент отправляет

Код:
procedure TForm1.Button1Click(Sender: TObject); // client
var
  DataBlock : TDataBlock;
  Buf: TIdBytes;
begin
  DataBlock.cmd := 0;
  DataBlock.nick := 'myNick';
  DataBlock.msg := 'message';
  Buf := RawToBytes(DataBlock, sizeOf(DataBlock));
  IdTCPClient1.IOHandler.Write(buf);
end;
3) сервер принимает

Код:
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext); // server
var
  DataBlock: TDataBlock;
  Buf: TIdBytes;
  i: Integer;
begin
  AContext.Connection.IOHandler.ReadBytes(buf,sizeof(buf),false);
  BytesToRaw(buf, DataBlock, sizeof(DataBlock));
  Form1.Memo1.Lines.Add(DataBlock.msg);
end;
но сервер ни чего не выводит в свой MEMO!
хелп ми, Комрады!

Последний раз редактировалось Adamrus; 05.01.2011 в 01:39.
Adamrus вне форума Ответить с цитированием
Старый 05.01.2011, 03:49   #3
veniside
Старожил
 
Регистрация: 03.01.2011
Сообщений: 2,508
По умолчанию

в исходниках инди читаем, что Execute
Цитата:
Occurs in the context of the peer thread
следовательно, работать с VCL внутри данного события нельзя.
"Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего."
veniside вне форума Ответить с цитированием
Старый 05.01.2011, 13:39   #4
Adamrus
Пользователь
 
Аватар для Adamrus
 
Регистрация: 26.11.2009
Сообщений: 59
По умолчанию

вот как Я делал раньше:
Код:
 AThread.Connection.ReadBuffer (CommBlock, SizeOf (CommBlock));
затем
Код:
if (CommBlock.Cmd = 'disconnect') then //комманда отключения клиента
    protocol.Lines.Add(TimeToStr(Time)+': Корректно отключился игрок '+CommBlock.MyNick)
Я не претендую на звание гуру, объясните, пожалуйста, как мне обойти этот момент
Adamrus вне форума Ответить с цитированием
Старый 05.01.2011, 16:08   #5
veniside
Старожил
 
Регистрация: 03.01.2011
Сообщений: 2,508
По умолчанию

Просто используй TStringList вместо мемо. Ничего визуального внутри IdTCPServer1Execute() трогать нельзя.
"Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего."
veniside вне форума Ответить с цитированием
Старый 05.01.2011, 19:53   #6
Adamrus
Пользователь
 
Аватар для Adamrus
 
Регистрация: 26.11.2009
Сообщений: 59
По умолчанию

Спасибо!
Над TStringList чуть позже покалдую.
Сделал так
Код:
BytesToRaw(buf, DataBlock, sizeof(DataBlock));
s := DataBlock.msg;
Form1.Memo1.Lines.Add(s);
теперь работает!
Adamrus вне форума Ответить с цитированием
Старый 06.01.2011, 00:16   #7
Adamrus
Пользователь
 
Аватар для Adamrus
 
Регистрация: 26.11.2009
Сообщений: 59
По умолчанию

подскажите, организовал на клиенте вот таким образом прослушку:
Код:
procedure TForm1.Timer2Timer(Sender: TObject);
var
  DataBlock: TDataBlock;
  Buf: TIdBytes;
  nick, msg, whom: ShortString;
begin
  IdTCPClient1.IOHandler.CheckForDataOnSource;
  while not IdTCPClient1.IOHandler.InputBufferIsEmpty do
    begin
      IdTCPClient1.Socket.ReadBytes(buf,sizeof(DataBlock),TRUE);
      BytesToRaw(buf, DataBlock, sizeof(DataBlock));
      nick := DataBlock.nick;
      whom := DataBlock.whom;
      msg := DataBlock.msg;
      AddColoredLine(Form1.RichEdit1,TimeToStr(Time)+': '+nick+' -> '+whom+': '+msg,clGray);
    end;

end;
работает, но вопрос как без таймера проверять прислал ли нам что-либо сервер?

2 вопрос: кроме айпи адреса, что уникального есть при подключении клиента к серверу, м.б. индекс потока, так как им воспользоваться?
Код:
procedure TForm1.IdTCPServer1Connect(AContext: TIdContext);
begin
  AddColoredLine(Form1.RichEdit1,Timetostr(Time)+': подключился IP='+AContext.Binding.PeerIP,clGreen);
end;

Последний раз редактировалось Adamrus; 06.01.2011 в 08:22.
Adamrus вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Компоненты Indy10 zevs5 Работа с сетью в Delphi 4 19.10.2015 15:44
UTF-8 и Indy10 Darw1n Работа с сетью в Delphi 12 21.06.2010 01:27
Проблемы при установке InDy10 Пепел Феникса Компоненты Delphi 2 18.02.2009 16:35