Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Интернет и сети
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 25.11.2010, 04:00
ravehog ravehog вне форума
Прохожий
 
Регистрация: 25.11.2010
Адрес: Санкт-Петербург
Сообщения: 7
Репутация: 10
Вопрос Indy TCP, активный двусторонний обмен короткими текстовыми пакетами. Как?

Доброго времени суток всем.

Излазил десятки русско- и англоязычных форумов в поисках ответа, так и не нашел ничего стоящего. Вопрос следующий: как, имея на руках компоненты Indy, построить активный двусторонний обмен данными (длина строк в среднем: 5-500 байт)? Т.е. обе стороны в любой момент могут выступить в роли передающей стороны. Использую Delphi 7 и Indy 9, но проект еще не зашел настолько далеко, чтобы сложно было перелопатить на другие версии при необходимости.

В данный момент работаю с IdTCPServer и IdTCPClient, установленными на сервер и клиент соответственно. Протокол самопальный, текстовый; во время работы клиента, в зависимости от нажатых пользователем клавиш, происходит отправка данных серверу; задача сервера же - отправлять данные клиенту по таймеру, а не в качестве "ответа" на присланные пакеты. Естественно, клиентов несколько, и данные им отправляются совершенно разные. Таймер сам по себе выставлен на 15 мс, но строка данных для отправки клиенту формируется в зависимости от происходящего на сервере, т.е. не каждый тик.

Соответственно, попытки устроить это через CommandHandler, каждые 15-25 мс спрашивая сервер, "не случилось ли что нового?", приводят к жуткому падению производительности из-за постоянных ответов типа "ничего". Нужно, чтобы сервер сам выступал в роли отправителя данных без запроса клиента на это, когда пакет данных для клиента будет подготовлен.

Пытался решить с помощью события OnExecute, так оно работает только тогда, когда клиент что-то присылает. Пытался воспользоваться IdThreadManager'ом, но не научился "вытаскивать" нужные потоки из списка. Ставить и на клиент, и на сервер по паре компонентов TCPClient/TCPServer - плохая идея, т.к. сервер имеет открытый постоянный IP-адрес, а вот клиент может запросто подключаться из какой-нибудь сети через шлюзы, маршрутизаторы и прочий ужас, делающий обратное подключение невозможным. В общем, пока безрезультатно.
Ответить с цитированием
  #2  
Старый 25.11.2010, 13:19
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

В свое время похожее делать пытался, т.е. чтобы сервер был инициатором отправки. Не нашел ничего лучше, чем переписать на WinSock. Сам ниче не придумал, а на форумах твердили, что это нереально в Indy.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием
  #3  
Старый 25.11.2010, 18:00
ravehog ravehog вне форума
Прохожий
 
Регистрация: 25.11.2010
Адрес: Санкт-Петербург
Сообщения: 7
Репутация: 10
По умолчанию

Вы не поверите, но эта фигня работает! Шедевр ослиной простоты.

Если на клиент добавить компонент idTCPClient и idTelnetClient, забитые на два разных порта, а на сервере - два idTCPServer на те же порты... По паре "TCP Client - TCP Server" сделать передачу команд на CommandHandler, а по паре "Telnet Client - TCP Server" - зацикленную передачу данных от сервера к клиенту, не выходя из процедуры OnConnect (в цикл встроены Sleep и Application.ProcessMessages)... То получаем непрерывный поток данных от сервера к клиенту по паре сервер-телнет, который управляется программно данными, посылаемыми через пару сервер-клиент ТСР (поскольку телнет постоянно что-то читает и отправить свои данные уже не может). Естественно, со всякими там обработчиками исключений на предмет дисконнекта клиента или просто желания его покинуть этот "поток"...

Жестокая таки штука! Сумрачный, блин, гений... Сижу как доской по голове ударенный, ну и решение.

p.S. Почему телнет? По-моему, единственное, что не вешает интерфейс клиента, когда пытается читать данные, если они еще не пришли с сервера. Попытки наладить через ТСР клиент и readln с таймаутом ничего не дали.

Последний раз редактировалось ravehog, 25.11.2010 в 18:05.
Ответить с цитированием
  #4  
Старый 25.11.2010, 18:03
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

как-то нехорошо))) лучше все-таки на WinAPI)
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием
  #5  
Старый 25.11.2010, 18:11
ravehog ravehog вне форума
Прохожий
 
Регистрация: 25.11.2010
Адрес: Санкт-Петербург
Сообщения: 7
Репутация: 10
По умолчанию

Winsock медленный слишком, у меня приоритетная задача - сделать как можно скорейшую передачу данных... А winsock думает по 30-50 мс над каждым пакетом, вешая и остальные подключения, насколько я помню его программирование, когда им занимался... Эта же штука при трех подключенных клиентах расфасовывает пакеты раз в 15-25мс без задержек, причем "все как надо", данные разных клиентов не смешиваются.
Ответить с цитированием
  #6  
Старый 26.11.2010, 00:10
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Ну не надо, не надо. WinSock над пакетами думает только в случае плохо написанного кода. Тот же инди в конце концов сводится к WinSock. По другому в винде просто невозможно работать с интернетом (если конечно не рассматривать драйвера нулевого кольца защиты, ассемблер, ручную реализацию протоколов TCPIP и UDP и т.д. Индейцы этим не увлекаются )

Я сам недавно писал свой компонент TCPIP Server. По трем причинам: 1) индейцы хреново работают с русским языком 2) нет возможности модифициорвать их код под свою задачу (если конечно не копаться в нем месяц-другой) и 3) индейцы каждому как я понял создают свой поток. А мне это не надо - мне нужен сервак последовательный. Работает у меня по скорости более чем нормально. Ничем не хуже индейских серверов.

А блочит WinSock только в случае, если не отключить блокировку, что делается двумя строками:
Код:
imode:=1;
ioctlsocket(Sock,FIONBIO,imode);
как-то так.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.

Последний раз редактировалось Bargest, 26.11.2010 в 00:15.
Ответить с цитированием
  #7  
Старый 26.11.2010, 01:22
ravehog ravehog вне форума
Прохожий
 
Регистрация: 25.11.2010
Адрес: Санкт-Петербург
Сообщения: 7
Репутация: 10
По умолчанию

Что ж, спасибо, буду смотреть. Раньше мне казалось, что winsock сам по себе устаревший до немогу. Если он способен работать хотя бы на той же скорости, что и инди - будет гораздо удобнее. Т.к. процедура отгрузки данных клиентам в случае с инди выполняется параллельно с остальными серверными делами, что выливается в необходимость написания кучи обработчиков возможных ошибок (динамических массивов там - хоть голову сломай).

Сильно усложняет работу то, что IP клиента может быть динамическим и спрятанным в сетевую архитектуру по самые уши.

Последний раз редактировалось ravehog, 26.11.2010 в 01:31.
Ответить с цитированием
  #8  
Старый 26.11.2010, 01:36
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Вообще winSock - часть WinAPI => работает чуть ли не с самыми основами винды. Кроме него работать с инетом позволит ток асма, и то с трудом. Так что WinSock работает не "хотя бы на той же скорости, что и инди", а МИНИМУМ на той же скорости, что и инди)))
Я когда-то писал какую-то прогу на инди. Меня там че-то задолбало с отправкой. Так вот я покопался в индейском сервере, нашел-таки там Socket и сделал отправку по нему через WinSock функцию. заработало. Что еще раз подтверждает то, что индеец тоже на WinSock'е
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием
  #9  
Старый 26.11.2010, 02:05
ravehog ravehog вне форума
Прохожий
 
Регистрация: 25.11.2010
Адрес: Санкт-Петербург
Сообщения: 7
Репутация: 10
По умолчанию

Ну, сейчас посмотрю, что у меня из этого выйдет... Как бы это ни было похоже на кручение кардана руками... Еще есть TClientSocket и прочие, но, мне кажется, они настолько же глупы, насколько и компоненты TcpClient/TcpServer...

...прошло пять часов...

Убейте меня, сокеты рушат мои мозги %) вытащил запылившиеся TServerSocket и TClientSocket, которые в 7м Делфи убрали с доски компонентов, щас буду их пытать...

Последний раз редактировалось ravehog, 26.11.2010 в 07:03.
Ответить с цитированием
  #10  
Старый 26.11.2010, 12:02
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Да, мне тоже поначалу выносило мозг куда подальше. А потом ниче, привык механизм подключения сложный, много каких-то функций, а сама работа проще топора: Send и Recv делай когда хошь.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 14:38.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter