![]() |
|
Модераторы: Snowy, Poseidon, MetalFan |
![]()
|
|
| Antony41 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 332 Регистрация: 27.12.2008 Репутация: нет Всего: 1 |
Привет всем!
Ребят нужна оперативная помощь. Я пишу многопоточный сервер/клиент на TServerSocket и TClientSocket Делаю так: У меня есть запись(record) определенной структуры в ней есть переменная fCommand: Word; Я заполняю эту структуру данными и передаю таким же образом эти данные принимаются затем структура заполняется даннымии распознается проблема в том что в локальной сети всё без ошибок, а вот по инету помимо моих пакетов приходят еще какие то данные которые не распознаются (т.е. например вместо команды fCommand содержит 0), что это за данные, чем отличается передача данных в локальной сети от передачи через инет? |
|||
|
||||
| kami |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 6 Всего: 72 |
как принимаешь и передаешь?
Что-то мне подсказывает (стандартная ошибка), что не учитываются результаты Socket.ReceiveBuf и Socket.SendBuf Добавлено через 7 минут и 21 секунду
Ой-е, вопрос отменяется. Не работаю и не буду работать в многопоточном режиме, не знаю, как там всё устроено. |
|||
|
||||
| Antony41 |
|
||||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 332 Регистрация: 27.12.2008 Репутация: нет Всего: 1 |
передаю так
FillTData это
//принимаю так. это соответственно происходит в потоке который постоянно проверяет на входящие данные
|
||||||||
|
|||||||||
| Antony41 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 332 Регистрация: 27.12.2008 Репутация: нет Всего: 1 |
Смотрите получается так:
сервак шлет данные и сразу получает какие то пустые пакеты, хотя клиент не отправлял данные я имею ввиду что команды или пакеты я не посылал в ответ серверу. Предполагаю что когда сервер шлет какой либо пакет, то стандартно приходят какие то данные о подтверждении, что пакет этот доставлен, но так как у меня эти данные преобразутся в мою структуру, то я вижу пустой пакет(record) возможен ли такой вариант? |
|||
|
||||
| kami |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 6 Всего: 72 |
мне бы такую уверенность, что пришло данных ровно на 1 структуру, ни байтом больше или меньше. Даже в локалке вероятность такого (+-) достаточно велика. Не говоря уже про глобальную сеть. Ввести проверки, сколько пришло. Если меньше - ждать следующей порции. Если больше - выбирать SizeOf данных, а хвост - запоминать для стыковки со следующим пакетом. Добавлено через 4 минуты и 8 секунд Поэтому нужно анализировать количество реально прочитанного Вот еще что непонятно - сокет создан в основном потоке, так (лежит-то он на форме)? Почему же обращение по выборке данных идет из дополнительного? Это несколько не-потокобезопасно. |
|||
|
||||
| Antony41 |
|
||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 332 Регистрация: 27.12.2008 Репутация: нет Всего: 1 |
Это ведь не Визуальный компонент почему не потокобезопасно?
тоесть так?
Это сообщение отредактировал(а) Antony41 - 11.2.2013, 20:43 |
||||||
|
|||||||
| kami |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 6 Всего: 72 |
не совсем. Под анализом я имел ввиду проверку i Вот так делается у меня:
Давайте возьмем за аксиому, что переключение между потоками происходит в любой момент. Этот момент определяется виндой и повлиять на него возможно только специальными методами, например - использованием объектов синхронизации (критические секции, мьютексы, евенты, сообщения). Допустим, что Винда решила переключиться в основной поток после выполнения (а может, и во время выполнения) этой строчки: И в основном потоке сокет закрывается (ну, прервалось соединение - бывает и такое). И обратно переключается уже после того, как сокет закрыт. Соответственно, всякие обращения типа Read, дальшейшее чтение ReceiveLength и т.п. будут как минимум невалидными, а как максимум - приведут к ошибке работы с памятью. Добавлено через 3 минуты и 22 секунды И то - далеко не факт, что произойдет моментальное переключение на нужный поток. Например, в случае использования критических секций это гарантировать нельзя. Некоторую гарантию дает только SendMessage, которая, в частности, используется (-лась, по крайней мере в D7) в Synchronize |
|||
|
||||
| Antony41 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 332 Регистрация: 27.12.2008 Репутация: нет Всего: 1 |
тоесть Вы хотите сказать, что лучше бы было использование компонента сокета внутри потока?
хотя эти действия у меня заключены в try except и finally за примерчик спасибо отдельное |
|||
|
||||
| kami |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 6 Всего: 72 |
забыл сказать - этот код из события OnRead компонента. Заводить поток, чтобы без перерыва читать оттуда данные, а отправлять другие данные из основного потока - нельзя. Добавлено через 4 минуты и 29 секунд
Как минимум - создание и активация сокета в OnExecute потока. Но в этом случае для правильной работы сокета в потоке нужно организовать цикл выборки сообщений. В том случае, если тип у сокета (свойство ClientType)- ctNonBlocking. Если выставлен ctBlocking - ничем помочь не могу, не работал с этим режимом. А чем вызвано желание сетевой работы именно в доп.потоке? |
|||
|
||||
| Antony41 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 332 Регистрация: 27.12.2008 Репутация: нет Всего: 1 |
||||
|
||||
| kami |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 6 Всего: 72 |
Это не примерчик, вот примерчик Реально использующийся уже несколько лет код, не претерпевший почти никаких изменений с тех пор UPD: поменял ссылку на более поздний пост. Это сообщение отредактировал(а) kami - 11.2.2013, 21:15 |
|||
|
||||
| Antony41 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 332 Регистрация: 27.12.2008 Репутация: нет Всего: 1 |
Я так понимаю это всё в не блокирующем режиме? потому что в блокирующем у меня данные вообще не приходят в событии OnRead
Это сообщение отредактировал(а) Antony41 - 11.2.2013, 21:32 |
|||
|
||||
| kami |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 6 Всего: 72 |
в блокирующем несколько другая система - там (вроде, могу ошибаться) на каждое соединение заводится отдельный поток, в котором всё и вертится. Но - он мне изначально не понравился, посему - даже не разбирался с ним. Это не значит, что блокирующий режим - плохой! Просто я не умею его готовить. Кстати, там в примере - большой недостаток. Во всех событиях OnRead последним оператором должно быть Data.Free, иначе пойдут утечки. Это сообщение отредактировал(а) kami - 11.2.2013, 21:41 |
|||
|
||||
| Antony41 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 332 Регистрация: 27.12.2008 Репутация: нет Всего: 1 |
Про сервер это так, но я имею ввиду клиента. т.е. сервер у меня в поточном режиме(blocking) а клиент впринципе тоже был в (blocking).
И вот теперь я сижу и думаю. Я понимаю что блочный режим для сервера нужен для того что бы поддерживать соединения в отдельном потоке и это нужно для того что бы сервак не зависал, НО зачем клиенту блочный режим ведь у него только одно соединение, или это нужно для поддержки соединений с несколькими серверами так что ли? В данном случае у меня один сервер и значит что мне не нужно использовать поточный режим для клиента? |
|||
|
||||
| kami |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 6 Всего: 72 |
можно поспорить. Я не думаю, что у Вас в коде производится настолько ресурсоемкая работа с принимаемыми/отправляемыми данными (или их настолько много принимается/отправляется за единицу времени), что это замедлит работу основного потока. Чаще всего, "заморозка" происходит из-за неправильных алгоритмов обработки данных в неблокирующем режиме.
Один ClientSocket - одно соединение. А сделано, я думаю, чтобы использовать один и тот же подход к обработке данных. Согласитесь, нелогично было бы на клиенте ориентироваться на OnRead|OnWrite и т.п., а на сервере - использовать потоки. "Всё должно быть единообразно - подстрижено, покрашено, посыпано песком" (с) армейское выражение. Добавлено через 2 минуты и 41 секунду Аргумент в пользу неблокирующего режима - создание на каждое соединение дополнительного потока считаю расточительством. Что будет, если количество живых подключений к серверу будет в районе 1000? Вы представляете себе, как винде будет тяжко разрулить такое количество потоков? |
|||
|
||||
![]()
|
| Правила форума "Delphi: Сети" | |
|
|
Запрещено: 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делится вскрытыми компонентами
Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Snowy, Poseidon, MetalFan. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Delphi: Сети | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |