|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
Indy TCP, активный двусторонний обмен короткими текстовыми пакетами. Как?
Доброго времени суток всем.
Излазил десятки русско- и англоязычных форумов в поисках ответа, так и не нашел ничего стоящего. Вопрос следующий: как, имея на руках компоненты 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
|
||||
|
||||
Да, мне тоже поначалу выносило мозг куда подальше. А потом ниче, привык механизм подключения сложный, много каких-то функций, а сама работа проще топора: Send и Recv делай когда хошь.
jmp $ ; Happy End! The Cake Is A Lie. |