eXeL@B —› Программирование —› Сокеты, трэды и Делфи. Клиент-сервер. |
Посл.ответ | Сообщение |
|
Создано: 23 февраля 2007 07:05 · Личное сообщение · #1 Смысл такой: есть ведущие (тип I) и ведомые (тип II) клиентские проги. Ведомые ставятся на компы, запускаются автоматом и содержат несколько видов функций (аля макросов). Ведущие проги ставятся на другие компы и позволяют рулить ведомыми (здесь юзер кликнул баттон - на ведомом компе выполнилось действие). На всё это хозяйство должен быть один сервер, так чтобы и ведущие и ведомые к нему коннектились, а ведомые получали указания от сервера от ведущих. Немного мудрёно, поэтому поясню: суть сервера - интерпретировать команды и выступать посредником между парой "ведущий-ведомый". Т.е. всёго 2 типа клиентов. Ну во всяком случае для того что я описал я вижу именно такую схему. Видится в этой задача мне всё, кроме вот чего: ведомые работают на неблокирующем сокете, а ведущие - на блокирующем (каждому такому клиенту - по трэду). Вопрос вот в чем: как безопасно переслать команду из потока ведущего в поток ведомого? ----- Я медленно снимаю с неё UPX... *FF_User* |
|
Создано: 23 февраля 2007 11:27 · Личное сообщение · #2 |
|
Создано: 23 февраля 2007 11:33 · Личное сообщение · #3 |
|
Создано: 23 февраля 2007 11:44 · Поправил: s0larian · Личное сообщение · #4 AlexZ, я делал такие вещи вот как: - сервер: имеет UI (главный поток) и ещё один поток для обработки всех клиентских соединений. Поток имеет listening socket а также список connected sockets. Почти все операции non-blocking: recv(), listen() - реализутся через select(). send() можно делать в blocking - так проще. Дополнительные потоки не нужны. - клиенты: имеют UI (или не создают ничего видимого) и ещё один поток который делает connect() и потом recv() в blocking режиме. Тут всё просто - recv() возвращаеццо, парсишь сообщение и передаёшь данные в главный поток через PostMessage(). В главном потоке, например, добавляешь строчку в list box, и выполняешь действие. voila! З.Ы. это все а win32 API, но в Delphi будут компоненты для всего этого. Если нужна помощь на С++/API - спрашивай. |
|
Создано: 24 февраля 2007 03:34 · Личное сообщение · #5 |
|
Создано: 26 февраля 2007 10:28 · Личное сообщение · #6 |
|
Создано: 26 февраля 2007 22:44 · Личное сообщение · #7 s0larian, прогресса пока нет, из отпуска выйду на след. неделе и снова воевать с клиентами С знаю плохо "сам не разговаривать, только понимать". К счастью, ведомые клиенты уже есть и к сожалению они ужасны, поэтому задача состоит в том, чтобы посредством нормального интерфейса ведущих клиентов управлять ведомыми через сервер. "Вот такой вот геморой нам придумала партия" ----- Я медленно снимаю с неё UPX... *FF_User* |
|
Создано: 28 февраля 2007 09:58 · Личное сообщение · #8 Я вот тоже воюю с сотевыми приблудами ))) Мой прога применяет TServerSocket и раз в n сек. рассылает всем законнекченным клиентам один и тот же буфер. А клиенты а-ля TClientSocket это все принимают и что-то делают свое черное с принятым от сервера буфера. Так вот глюк в том что от сервера идет пакет скажем на 2308 байт, а вот не все клиенты принимают полностью этот пакет! бывает что в момент времени Т1 клиент К1 принимет 1460 байт, а через хз ско-ко времени и периодов приема может принять полностью 2308 байт! Вот хз как быть дальше, пока ищу ответ в сорцах, мож найду ----- My love is very cool girl. |
|
Создано: 28 февраля 2007 17:04 · Поправил: s0larian · Личное сообщение · #9 theCollision, какой протокол ты используешь? TCP? Если так, то данные могут быть разбиты на сколько угодно сетевых пакетов (то что видит sniffer). TCP это поток данных и recv() может вернуться сколько угодно раз - зависит от того сколько приходит сетевых пакетов и конфигурации сокета. (то есть ты можешь сказать что б recv() возврачал минимум N байтов) Обычно люди пишут мелкий заголовок такого типа:
потом идут данные. Ну и клиент вызывает recv() пока не получит sizeof(MessageHeader) а потом ещё пока не получит всё сообщение. |
|
Создано: 28 февраля 2007 22:18 · Личное сообщение · #10 Вот кусок рассылки сервером: procedure TNkTecServer.Send; var I : Integer; begin for I := 0 to FServer.Socket.ActiveConnections - 1 do begin CopyMemory(FServer.Socket.Connections[I].Data,Buffer,FSizeOfBuf); FServer.Socket.Connections[I].SendBuf(FServer.Socket.Connections[I].Da ta^, FSizeOfBuf); Sleep(200); end; end; Вот в что написано у меня в обработчике TClientSocket.OnRead : SizeOfBuf := Socket.ReceiveLength; Socket.ReceiveBuf(Buffer,SizeOfBuf); Дальше махинации с принятым буфером. Вроде бы все ок! Но при работе серверной части: 01.03.2007 08:38:11 [options.xml] Opened 01.03.2007 08:38:13 [Network] Connect: 10.128.3.56 01.03.2007 08:38:38 [Network] Connect: 10.128.3.56 01.03.2007 08:38:53 [Network] Disconnect: 10.128.3.56 01.03.2007 08:38:58 [Network] Connect: 10.128.3.56 01.03.2007 08:39:13 [Network] Disconnect: 10.128.3.56 .................................................... 01.03.2007 08:57:58 [Network] Connect: 10.128.3.56 01.03.2007 08:58:00 [Network] Disconnect: 10.128.3.56 01.03.2007 08:58:13 [Network] Disconnect: 10.128.3.56 Вот ну никак не пойму, почему клиент, два раза коннектиться и дисконнектиться и постоянно коннектдисконнект ( ----- My love is very cool girl. |
|
Создано: 02 марта 2007 04:28 · Личное сообщение · #11 theCollision, вот та же шняга и у меня... Чисто для статистики стал добавлять в лог коннекты/дисконнекты и пошло нахъ =( Ещё один ньюанс: в свойствах Т-сокета АйПи - это не АйПи клиента, а АйПи самой верхней машины, т.е. при клиентских коннектах от одного провайдера получаем ИП прова один и тот же. ----- Я медленно снимаю с неё UPX... *FF_User* |
|
Создано: 02 марта 2007 10:00 · Личное сообщение · #12 |
|
Создано: 02 марта 2007 11:05 · Личное сообщение · #13 |
|
Создано: 02 марта 2007 14:03 · Личное сообщение · #14 |
|
Создано: 02 марта 2007 15:11 · Личное сообщение · #15 theCollision пишет: Я не просто могу, я вынужден, потому что я начал писать свой компонент ))) Жалко что абстрактного класса нету, под сокеты, который бы описывал че может TSeverSocket ((( TAbstractSocket, TCustomSocket, TCustomServerSocket, TServerSocket? хелп к дельфе рулит. для последнего есть даже "Using server sockets", с примерами. На torry.net фришных socket серверов куча. Сильно хочется пример - выкачать несколько и посмотреть что и как. Есть синапс (реально рулит), но там не объекты, там тоже типа апи и только блокирующие сокеты. |
|
Создано: 02 марта 2007 22:02 · Личное сообщение · #16 n1kto Ты глянь на эти сорцы ))), Там же уже много вещей переопределено и сделано!!! А абстрактный класс - это когда не содержатся, только и только виртуальные методы. Замечу, если ты сейчас создашь объекты от классов что ты предложил, компиллер сделает объекты!!! А из букваря известно, что от абстрактных классов - не может быть создан объект!!! s0larian Я не могу определиться, какую модель мне брать? На портах-завершения? Тогда где почитать, чтобы по толковей описано было? ----- My love is very cool girl. |
|
Создано: 02 марта 2007 22:42 · Личное сообщение · #17 theCollision пишет: А абстрактный класс - это когда не содержатся, только и только виртуальные методы. В этом смысле абстрактными в дельфи являются интерфейсы. определи и трахайся до посинения theCollision пишет: А из букваря известно, что от абстрактных классов - не может быть создан объект!!! определяем интерфейс и пытаемся сделать из него объект. не получается. значит, компилятор не работает В дельфи от любого класса может быть создан объект, так как все классы происходят от общего предка имеющего неабстрактное содержимое. курим букварь по дельфи я не очень понял, чем тебя классическая модель автомата не устраивает? биндишь сокет, на accept вешаешь создание нового треда, который рулит конкретным соединением... вроде все просто? кстати, два коннекта и дисконнекта могут расти именно отсюда - порт-листен и реально рабочий - разные. |
|
Создано: 02 марта 2007 23:37 · Личное сообщение · #18 |
|
Создано: 05 марта 2007 13:55 · Личное сообщение · #19 |
eXeL@B —› Программирование —› Сокеты, трэды и Делфи. Клиент-сервер. |