![]() |
|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
![]() Доброго времени суток всем.
Излазил десятки русско- и англоязычных форумов в поисках ответа, так и не нашел ничего стоящего. Вопрос следующий: как, имея на руках компоненты Indy, построить активный двусторонний обмен данными (длина строк в среднем: 5-500 байт)? Т.е. обе стороны в любой момент могут выступить в роли передающей стороны. Использую Delphi 7 и Indy 9, но проект еще не зашел настолько далеко, чтобы сложно было перелопатить на другие версии при необходимости. В данный момент работаю с IdTCPServer и IdTCPClient, установленными на сервер и клиент соответственно. Протокол самопальный, текстовый; во время работы клиента, в зависимости от нажатых пользователем клавиш, происходит отправка данных серверу; задача сервера же - отправлять данные клиенту по таймеру, а не в качестве "ответа" на присланные пакеты. Естественно, клиентов несколько, и данные им отправляются совершенно разные. Таймер сам по себе выставлен на 15 мс, но строка данных для отправки клиенту формируется в зависимости от происходящего на сервере, т.е. не каждый тик. Соответственно, попытки устроить это через CommandHandler, каждые 15-25 мс спрашивая сервер, "не случилось ли что нового?", приводят к жуткому падению производительности из-за постоянных ответов типа "ничего". Нужно, чтобы сервер сам выступал в роли отправителя данных без запроса клиента на это, когда пакет данных для клиента будет подготовлен. Пытался решить с помощью события OnExecute, так оно работает только тогда, когда клиент что-то присылает. Пытался воспользоваться IdThreadManager'ом, но не научился "вытаскивать" нужные потоки из списка. Ставить и на клиент, и на сервер по паре компонентов TCPClient/TCPServer - плохая идея, т.к. сервер имеет открытый постоянный IP-адрес, а вот клиент может запросто подключаться из какой-нибудь сети через шлюзы, маршрутизаторы и прочий ужас, делающий обратное подключение невозможным. В общем, пока безрезультатно. |
#2
|
||||
|
||||
![]() В свое время похожее делать пытался, т.е. чтобы сервер был инициатором отправки. Не нашел ничего лучше, чем переписать на WinSock. Сам ниче не придумал, а на форумах твердили, что это нереально в Indy.
jmp $ ; Happy End! The Cake Is A Lie. |
#3
|
|||
|
|||
![]() Вы не поверите, но эта фигня работает! Шедевр ослиной простоты.
Если на клиент добавить компонент 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
|
||||
|
||||
![]() как-то нехорошо))) лучше все-таки на WinAPI)
jmp $ ; Happy End! The Cake Is A Lie. |
#5
|
|||
|
|||
![]() Winsock медленный слишком, у меня приоритетная задача - сделать как можно скорейшую передачу данных... А winsock думает по 30-50 мс над каждым пакетом, вешая и остальные подключения, насколько я помню его программирование, когда им занимался... Эта же штука при трех подключенных клиентах расфасовывает пакеты раз в 15-25мс без задержек, причем "все как надо", данные разных клиентов не смешиваются.
|
#6
|
||||
|
||||
![]() Ну не надо, не надо. 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
|
|||
|
|||
![]() Что ж, спасибо, буду смотреть. Раньше мне казалось, что winsock сам по себе устаревший до немогу. Если он способен работать хотя бы на той же скорости, что и инди - будет гораздо удобнее. Т.к. процедура отгрузки данных клиентам в случае с инди выполняется параллельно с остальными серверными делами, что выливается в необходимость написания кучи обработчиков возможных ошибок (динамических массивов там - хоть голову сломай).
Сильно усложняет работу то, что IP клиента может быть динамическим и спрятанным в сетевую архитектуру по самые уши. Последний раз редактировалось ravehog, 26.11.2010 в 01:31. |
#8
|
||||
|
||||
![]() Вообще winSock - часть WinAPI => работает чуть ли не с самыми основами винды. Кроме него работать с инетом позволит ток асма, и то с трудом. Так что WinSock работает не "хотя бы на той же скорости, что и инди", а МИНИМУМ на той же скорости, что и инди)))
Я когда-то писал какую-то прогу на инди. Меня там че-то задолбало с отправкой. Так вот я покопался в индейском сервере, нашел-таки там Socket и сделал отправку по нему через WinSock функцию. заработало. Что еще раз подтверждает то, что индеец тоже на WinSock'е jmp $ ; Happy End! The Cake Is A Lie. |
#9
|
|||
|
|||
![]() Ну, сейчас посмотрю, что у меня из этого выйдет... Как бы это ни было похоже на кручение кардана руками... Еще есть TClientSocket и прочие, но, мне кажется, они настолько же глупы, насколько и компоненты TcpClient/TcpServer...
...прошло пять часов... Убейте меня, сокеты рушат мои мозги %) вытащил запылившиеся TServerSocket и TClientSocket, которые в 7м Делфи убрали с доски компонентов, щас буду их пытать... Последний раз редактировалось ravehog, 26.11.2010 в 07:03. |
#10
|
||||
|
||||
![]() Да, мне тоже поначалу выносило мозг куда подальше. А потом ниче, привык
![]() jmp $ ; Happy End! The Cake Is A Lie. |