Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2007.02.25;
Скачать: [xml.tar.bz2];

Вниз

Логика работы сокетов   Найти похожие ветки 

 
Eraser ©   (2006-09-10 00:05) [40]

> [38] _Sergey_ ©   (09.09.06 23:58)


> Хотя, в такой реализации сервер будет менее защищен от "неправильных"
> клиентов, поскольку можно будет просто подключиться, и не
> посылать ни одного байта

это легко обойти такой схемой:
1. Клиент подключается к серверу и отсылает ему 1 байт данных.
2. Сервер пытается считать из сокета 1 байт, если не получается - закрывает сокет, если получается - входит в критическую секцию.
3. Сервер отсылает 1 байт клиенту.
4. Клиент пытается считать 1 байт, если получается - отсылает пакет, если нет - убивает сокет.
5. Сервер принимает пакет и закрывает критическую секцию.

по моему степень надежности данной схемы довольно неплохая, по крайней мере в качестве "защиты от дурака" сгодится.


 
_Sergey_ ©   (2006-09-10 00:35) [41]

Конечно, сгодится. Но можно не 1 байт, а 7 или больше, для надежности (зафлудить будет тяжелее, т.к. если клиентом будет посылаться непрерывный поток данных, то вероятность встретить там исходную 7-байтную комбинацию оч. мала, а, если сервер получает не ее, можно сразу же серверу закрыть сокет).

И критическая секция не понадобится. Accept вызовется только после окончания обработки данных от текущего клиента. Всего у меня 1 поток. А до этого момента будет существовать только 1 канал связи.


 
Eraser ©   (2006-09-10 15:47) [42]

> [41] _Sergey_ ©   (10.09.06 00:35)


> зафлудить будет тяжелее, т.к. если клиентом будет посылаться
> непрерывный поток данных, то вероятность встретить там исходную
> 7-байтную комбинацию оч. мала, а, если сервер получает не
> ее, можно сразу же серверу закрыть сокет

от флуда и других злоумышленных атак данный метод не пойдет. если нужна настоящая защита - должен быть реализован настоящий анти-флуд, со списком "черных" IP, контролем от переполнения буффера, защитой от DOS-атак и т.п.


 
_Sergey_ ©   (2006-09-10 23:59) [43]

Со списком "черных" IP все понятно - SO_CONDITIONAL_ACCEPT, WSAAccept(), в процедуре - CF_REJECT. Контроль от переполнения буффера, как я понял - StrLCat (используется для "склейки" приходящих пакетов). А вот как защититься от DOS-атак? Шифровать пакеты, дак это не то. Может, занесение в черный список при оч. частых коннектах с определенного адреса, или большом числе "неправильных" пакетов с этого адреса. Было бы полезно знать. А сейчас реализовал предложенную логику, но только по более простой схеме (пока пренебрег безопасностью). Логика такова:
1) accept-им клиента
2) сразу же высылаем ему пакет с подтверждением об разрешении отправки данных
3) если клиенту не приходит данное разрешение за тайм-аут сек., то он уничтожает сокет, создает его заново и пытается законнектиться по тайм-ауту. Иначе (разрешение пришло) он отсылает данные.
4) Сервер принимает данные по тайм-ауту. Как только сервер приймет маркер окончания пакета данных, он высылает клиенту пакет с подтверждением об успешной доставке данных. При ошибке send подтверждения обработка пакета отменяется (защита от дублирования пакетов). Сервер закрывает сокет клиента и вызывает процедуру обработки принятого пакета. После чего снова переходит на Accept.
5) клиент принимает тайм-аут сек. пакет с подтверждением. Если он не получит этот пакет, то уничтожит сокет, создаст его заново, подключится и снова будет пытаться послать старый пакет через тайм-аут сек. Иначе (получил подтверждение) клиент закрывает сокет и вызывает процедуру формирования нового пакета. И снова повторяет цикл.

Отключил алгоритм Нагеля на стороне клиента. На стороне сервера после каждого accept отключаю этот алгоритм для сокета, связанного с клиентским.

Размер очереди в Listen заменил с максимальной до 1.

Кроме того, кажется нашел ответ на свой 2-ой вопрос, заданный в [0] ;)
Как показал эксперимент, слушающий сокет закрывается не сразу, поэтому к нему еще можно подконнектиться. Кажется так.

Нашел опасную описку. "Зависание" некот. клиентов, описанное выше, оказывается, было вызвано тем, что я отсылал пакет 0-го размера для проверки занятости сервера, используя конструкцию вида:
while send(...) = SOCKET_ERROR do goto reconnect;
На самом деле нужно было
if send(...) = SOCKET_ERROR then goto reconnect;

Кроме того, WSAAccept вклинивается в станд. обмен запрсами и ответами на транспортном уровне. И может создавать, как мне кажется, разл. нестандартные тайм-ауты и ситуации. Хотя, может быть, я здесь и ошибаюсь.

Результаты:
1) скорость работы 15 клиентов (тайм-ауты на переконнект - 2 сек., время формирования 1 пакета - меньше 0,5 сек) и 1 сервера, тестируемые на 1 машине через loopback, субъективно увеличилось где-то в 2 раза по сравнению с предыд. реализацией (стресс-тест, в реальности в таком режиме сервер работать не будет). [алгоритм Нагеля]
2) При анализе логов после стресс-теста обнаружилось почти полное отсутствие сообщений об занятости сервера [алгоритм Нагеля]
3) Исчезли те самые 2000 потерь пакетов на 20000 передач, описываемые выше. Раньше я просто исправлял эту ситуацию, перепередавая пакеты. Сейчас этого делать не нужно. [обратная связь + ликвидация_описки]
4) на машине W2k Pro SP4 с интегр. сетевой картой ранее были такие проблемы: после ~ 30 мин. работы винда вылетала с синим экраном, самопроизвольно перезагружаясь (автоперезагрузка при сбое отключена).
Причину по коду ошибки выяснить не удалось. При конфигурации: P4 3.0 HT, WinXP SP1, интегр. сет. такого не было. При текущей реализации сервер проработал на 1-ой машинке 5 часов без синих экранов. [слушающий сокет не создается/уничтожается с оч. большой частотой]
5) осталась проблемка: с включенным HT при стресс-тесте иногда клиенты вылетают с сообщением об ошибке обращения к памяти, адреса все время разные. При выключенном HT такая проблема исчезает. Вероятная причина: винда или ее библиотеки (включая сетевые) не всегда правильно работает на многопроцессорной машинке (процессоры хоть и виртуальные, но их все же формально 2 шт.). В старой реализации такая прблема проявлялась раза в 4 чаще. Сейчас - реже. Считаю это не проблемой моего приложения.

Т.е., улучшения налицо. Еще раз спасибо за подсказку. Оказалось, я искал решения на транспортном уровне. А надо было, как делают все протоколы, защищаться обратной связью с отправкой пакетов со служебными сообщениями.


 
Eraser ©   (2006-09-11 01:45) [44]

> [43] _Sergey_ ©   (10.09.06 23:59)


> А вот как защититься от DOS-атак?

если за опр. промежуток времени произошло опр. количесвто неудачных соединений с конкретного IP - заносить этот IP в черный список.. на опр. промежуток времени :)
хотя если нужна настоящая защита - при каждом соединений необходимо производить сначала сеанс аутентификации, потом сеанс авторизации и уже по защищенному каналу обмениваться данными. Либо производить аутентификацию/авторизацию при первой попытке связи клиента с сервером, а в дальнейшем уже использовать ранее сгенерированный ключ для шифрования данных. Второй вариант в вашем случае предпочтителен, т.к. генерация ключей с надежной криптоустойчиваостью - процесс небыстрый.. несколько секунд тратится.

> осталась проблемка: с включенным HT при стресс-тесте иногда
> клиенты вылетают с сообщением об ошибке обращения к памяти,
> адреса все время разные.

возможно в данном случае поможет ф-ия SetThreadAffinityMask, которая позволяет "привязать" поток к определенному процессору.. не знаю как оно будет работать с HT.. думаю нормально )

PS попробуйте использовать какой-нибудь готовый сервер, например TIdTCPServer и сравните скорость работы с вашей реализацией, возможно не стОит усложнять себе жизнь изобретая велосипеды, хотя может быть тут я не прав.


 
Сергей М. ©   (2006-09-11 08:47) [45]


> _Sergey_ ©   (09.09.06 00:16) [16]


Ну и понесло же тебя в дебри)
Нагородил ты себе, понимаешь, огромную кучу несуществующих проблем и теперь героически пытаешься разгрести эту кучу, хватаясь то за одно то за другое)

Зачем тебе нужна последовательная обработка кл.запросов на сервере, я так и не понял.. При грамотной реализации сервера он будет корректно и вовремя обрабатывать одновременные запросы сотен и тысяч столь же грамотно реализованных клиентов, и никакие пакеты никуда исчезать не будут при этом.


 
_Sergey_ ©   (2006-09-11 13:09) [46]


> PS попробуйте использовать какой-нибудь готовый сервер,
> например TIdTCPServer и сравните скорость работы с вашей
> реализацией, возможно не стОит усложнять себе жизнь изобретая
> велосипеды, хотя может быть тут я не прав.


В том-то и дело, что до того, как реализовывать сетевую логику работы на ф-иях библиотеки сокетов, я пробовал реализовать ее же с помощью различных компонентов:
1) стандартные TClientSocket, TServerSocket. Много "глюков": образование незакрытых соединений при активном тестировании, нет контроля над кол-вом создаваемых потоков (каналов связи), иногда выдают разные сообщения об ошибках в виде MessageBox-ов, при подключении Telnet-ом не определяет, что к серверу кто-то подключился, кроме того, при приеме данных ждет прихода хотя бы 1-го байта (причем, может ждать и 5 мин., и час, и два ...)...
2) Indy. Реализован полностью на блокирующих сокетах, даже есть св-во max числа подключений. Но: при подключении Telnet-ом не определяет, что к серверу кто-то подключился, кроме того, при приеме данных ждет прихода хотя бы 1-го байта (причем, может ждать и 5 мин., и час, и два ...); не понравилась инсталляция Indy 10 на D7 (инсталлятор даже не смог правильно подключить 10 версию, хотя он был специально предназначен для D7); не удалось отключать клиента внутри таймера, т.к. управление объектом, идентифицирующем соединение, реализуется только внутри процедуры обработки прихождения данных от клиента (название процедуры точно не помню), в Indy 10 была частично перестроена иерархия св-в для объектов и изменена сама иерархия объектов, что решило эту проблему ...
3) Пишу сейчас не из домашней машинки. Название не могу глянуть, но пробовал еще 1 пакет компонентов. Коммерческий продукт, реализации существуют для Borland C++ Builder, Borland Delphi и кажется, Kylix, для разных версий. Отдельно были компоненты, поддерживающие SSL. Но там не было св-ва, ограничивающего число подключений. Хотя, при подключении к такому серверному компоненту telnet-ом, он определил факт подключения, чего не смогли сделать компоненты, описанные в 1) и 2).

Поэтому решил написать сам. На более низком уровне, чем использование компонентов. Ниже - только работа с драйверами и написание своих драйверов. В такие дебри пускаться я не хочу. И теперь, мое приложение будет иметь баги MS (библиотека сокетов), Borland (компилятор), и мои. И никак не баги разработчиков компонентов. Кроме того, я могу настроить св-ва (адаптировать работу сокетов под свои нужды) и контролировать каждое соединение.

P.S> Когда я скачал документацию с оф. сайта по Indy 10 в *.html (запакованные), я ужаснулся. Если там код находится в таком же состоянии, как и документация, то я удивляюсь, как он вообще работает. Кто видел эту документацию, поймет меня.


 
_Sergey_ ©   (2006-09-11 13:26) [47]


> хотя если нужна настоящая защита - при каждом соединений
> необходимо производить сначала сеанс аутентификации, потом
> сеанс авторизации и уже по защищенному каналу обмениваться
> данными. Либо производить аутентификацию/авторизацию при
> первой попытке связи клиента с сервером, а в дальнейшем
> уже использовать ранее сгенерированный ключ для шифрования
> данных. Второй вариант в вашем случае предпочтителен, т.
> к. генерация ключей с надежной криптоустойчиваостью - процесс
> небыстрый.. несколько секунд тратится.


Т.е., SSL, или шифрование. На сегодняшний день нашел только 1 компонент, позволяющий шифровать данные, но он визуальный, и требует наличия формы. Я же хочу оставить свое приложение консольным. Сам написать модуль, обеспечивающий должный уровень шифрования, я не в силах. Готового не нашел. Могу реализовать что-то простенькое, что защитит только "от дурака".
Есть пример связывания Indy 9 (10) с библиотекой OpenSSL. Единственной библиотекой, как я понял, доступной для связывания с Delphi (с предварительной небольшой адаптацией). Но этот пример, как мне кажется, работает как-то "неправильно". В самом примере при переведении в активное состояние idTcpServer, связанного с OpenSSL, введена задержка по таймеру. Если эту задержку убрать, то возникают разного рода ошибки. Кроме того, при переведении этого же idTcpServer в неактивное состояние приложение с idTCPServer-ом "вываливается" по Access violation ... Чьи это проблемы - Indy или OpenSSL, я не знаю. Но проблемы налицо. Кроме того, я предполагаю, что будет не так-то просто связать консольное приложение на Delphi с OpenSSL, поскольку нужно написать некий промежуточный код, который позволил бы свести взаимодействие с библиотекой SSL к простому вызову процедур для открытия сертификата ... Есть еще вариант - 3 компонент. Но не хочу я использовать сторонние компоненты. Хотя, есть серьезные предположения, что как раз этот компонент реализован довольно "качественно". Что Вы можете посоветовать из числа готовых программных пакетов для применения с Delphi (консольное приложение) для шифрования или создания защищенных линий связи?


 
Сергей М. ©   (2006-09-11 13:30) [48]


> 1) стандартные TClientSocket, TServerSocket. Много "глюков":
>  образование незакрытых соединений


Это не "глюки". Это как минимум незнание особенностей реализации компонентов и/или нежелание читать их исх.тексты, благо они всегда имеются.


> нет контроля над кол-вом создаваемых потоков (каналов связи)


Есть такой контроль. Вполне успешно работающий.


> выдают разные сообщения об ошибках в виде MessageBox-ов


По-твоему, возникающие ошибки должны "замалчиваться" компонентами, так что ли ?


> при подключении Telnet-ом не определяет, что к серверу кто-
> то подключился


Вот уж глупости. И причем здесь вообще Telnet ? Компоненты эти реализуют транспортный уровень, ни больше ни меньше. Прикладной же уровень в этом случае целиком и полностью на твоей совести.


> при приеме данных ждет прихода хотя бы 1-го байта (причем,
>  может ждать и 5 мин., и час, и два


Не выдумывай.
В неблок.режиме ничего ждать не надо - о транспортных событиях в канале связи компоненты извещают асинхронно соответствующими своими событиями.

В блокирующем же режиме никто не запрещает воспользоваться select"ом для работы с транспортом по таймаутам.


> И никак не баги разработчиков компонентов


Нет там никаких сколь-либо серьъезных "багов".
А если и есть - на то имеются исх.тексты.


 
Rouse_ ©   (2006-09-11 13:31) [49]

Слушай, возьми ICS и не мучайся, давным давно Пиетта за нас все написал, ни убавить ни добавить (правда не весь функционал, но все-же) :)


 
_Sergey_ ©   (2006-09-11 13:33) [50]


> Зачем тебе нужна последовательная обработка кл.запросов
> на сервере, я так и не понял.. При грамотной реализации
> сервера он будет корректно и вовремя обрабатывать одновременные
> запросы сотен и тысяч столь же грамотно реализованных клиентов,
>  и никакие пакеты никуда исчезать не будут при этом.


По специфике работы моего серверного приложения оно не требует реализации сервера в многоклиентском виде, поскольку нагрузка на сервер минимальна, и, если сервер не может обслужить очередного клиента, значит, он занят непродолжительной процедурой обслуживания какого-то клиента. В данном случае последовательная обработка позволяет не "заморачиваться" с синхронизацией потоков, критическими секциями, позволяет не обходить тупиковые ситуации (когда один процесс заблокировал какой-то ресурс), поскольку и однопотоковый сервер в состоянии обслужить всех клиентов.


 
Сергей М. ©   (2006-09-11 13:56) [51]


> последовательная обработка позволяет не "заморачиваться"
> с синхронизацией потоков, критическими секциями


Это никак не вяжется с изначальным вопросом.
Берешь обычные TServer/ClientSocket или TTCPServer/Client и используешь их в неблок.режиме - вот тебе и послед.обработка и гарантированная доставка сообщений.


> однопотоковый сервер в состоянии обслужить всех клиентов


TServerSocket/TTCPServer в неблок.режиме как раз и реализуют однопоточный серверный транспорт.
И не понятно, к чему ты при этом упомянул TIdTCPServer - он заведомо многопоточный.


 
Eraser ©   (2006-09-11 16:06) [52]

> [50] _Sergey_ ©   (11.09.06 13:33)


> В данном случае последовательная обработка позволяет не
> "заморачиваться" с синхронизацией потоков, критическими
> секциями, позволяет не обходить тупиковые ситуации (когда
> один процесс заблокировал какой-то ресурс), поскольку и
> однопотоковый сервер в состоянии обслужить всех клиентов.

ну тут уже не раз повторили, что это ерунда, то что та пишешь.

какие проблемы с крит. секцией? 2 строчки кода (ну пусть 5, с учетом try..finally..end) это проблемы?
а вот реализация полностью однопоточного сервера, в том виде, что ты хочешь - вот это проблема.

насчет компонентов - согласен с Сергеем М., в таких базовых компонентах как TServer/ClientSocket или TIdTCPServer я глюков не встречал, они имеются в более сложных реализациях, но в этих компонентах - вряд ли.

> при приеме данных ждет прихода хотя бы 1-го байта (причем,
> может ждать и 5 мин., и час, и два ...);

см. свойство ReadTimeout.

> понравилась инсталляция Indy 10 на D7 (инсталлятор даже
> не смог правильно подключить 10 версию, хотя он был специально
> предназначен для D7

опять же - просто надо уметь готовить :) у меня проблем с инсталляцией не возникало.

> P.S> Когда я скачал документацию с оф. сайта по Indy 10
> в *.html (запакованные), я ужаснулся. Если там код находится
> в таком же состоянии, как и документация, то я удивляюсь,
> как он вообще работает. Кто видел эту документацию, поймет
> меня.

не знаю как на сайте, их chm файл меня вполне устраивал, сейчас правда пользуюсь встроенной справкой из BDS2006.

> Т.е., SSL, или шифрование.

не обязательно. я имел ввиду свою реализацию, к примеру, на базе MS Crypto API, что не так уж и трудно.


 
_Sergey_ ©   (2006-09-12 00:17) [53]


> TServerSocket/TTCPServer в неблок.режиме как раз и реализуют
> однопоточный серверный транспорт.

Это компоненты, создающие в неблок. режиме столько подключений, сколько клиентов попытается подключиться. В блок. режиме - другое дело.

IdTCPServer - компонент, сетевая логика которого основана на блок. сокетах. Вот к тому и упоминаю. А еще там св-во есть, MaxConnections называется. Оч. полезное св-во.


 
Eraser ©   (2006-09-12 00:36) [54]

> [53] _Sergey_ ©   (12.09.06 00:17)


> IdTCPServer - компонент, сетевая логика которого основана
> на блок. сокетах.

Эт я в курсе :)
его и советую использовать.


 
_Sergey_ ©   (2006-09-12 00:36) [55]


> Есть такой контроль. Вполне успешно работающий.

В свое время не нашел, хотя долго искал. Может, подскажете, как именно реализуется этот контроль?


> По-твоему, возникающие ошибки должны "замалчиваться" компонентами,
> так что ли ?

Нет. Но программа должна уметь правильно их обработать, оставляя за собой способность работать в автоматическом режиме, а не ждать нажатия пользователя на кнопку очередного MessageBox-а с ошибкой. Компоненты, на мой взгляд, должны обеспечить замену станд. процедуры вывода ошибки на ф-ию, определяемую программистом, в которую компонентом передается текстовое сообщение об ошибке или код ошибки. А как выводить и что с этим делать - задача программиста.


> Вот уж глупости. И причем здесь вообще Telnet ? Компоненты эти
> реализуют транспортный уровень, ни больше ни меньше. Прикладной же
> уровень в этом случае целиком и полностью на твоей совести.

Не вижу здесь глупости. Прикладной уровень то на моей совести. Но как я смогу отключить клиента, если я даже не знаю, что кто-то уже подключился к серверу. К примеру, в idTCPServer поставлю MaxConnections=1. Вызвать DOS для такого сервера проще не бывает - подключиться к нему телнетом. А тогда на совести, не на совести, а вся логика прикладного уровня не будет иметь никакого смысла, ведь сервер даже не будет знать, что единственный канал связи уже занят.


 
_Sergey_ ©   (2006-09-12 00:51) [56]


> Eraser © [54]

Боюсь, назад дороги нет :)
Можно сказать, что сейчас я доволен реализацией и работой. Может, следует попытаться защитить и усложнить обработку, но на первых порах неплохо.


 
_Sergey_ ©   (2006-09-12 00:53) [57]


> Rouse_ © [49]

Что такое ICS?


 
Eraser ©   (2006-09-12 01:21) [58]

> [56] _Sergey_ ©   (12.09.06 00:51)


> К примеру, в idTCPServer поставлю MaxConnections=1.

ну сколько ж раз говорить - не нужно ограничевать количество клиентов на транспортном уровне.. кроме доп. нагрузке на сеть и увеличению кол-ва ошибок это ни к чему не приведет.

> Что такое ICS?

компоненты, основанные на неблокирующих сокетах.

> Боюсь, назад дороги нет :)

код сервера:

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer,
 IdContext, IdGlobal;

type
 TfmMain = class(TForm)
   IdTCPServer1: TIdTCPServer;
   procedure IdTCPServer1Execute(AContext: TIdContext);
   procedure FormCreate(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 fmMain: TfmMain;
 csSync: RTL_CRITICAL_SECTION;

implementation

{$R *.dfm}

procedure TfmMain.FormCreate(Sender: TObject);
begin
 InitializeCriticalSection(csSync);
 IdTCPServer1.DefaultPort := 777;
 IdTCPServer1.Active := true;
end;

procedure TfmMain.IdTCPServer1Execute(AContext: TIdContext);
var
 Buf: TBytes;
 BufSize: Integer;
begin
 AContext.Connection.IOHandler.Write(Integer(1));
 AContext.Connection.IOHandler.ReadInteger; // Dummy value.
 try
   EnterCriticalSection(csSync);
   BufSize := AContext.Connection.IOHandler.ReadInteger; // Размер пакета.
   AContext.Connection.IOHandler.ReadBytes(Buf, BufSize); // Принимаем буффер.
 finally
   LeaveCriticalSection(csSync);
 end;
end;

end.

код клиента:

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
 IdGlobal;

type
 TfmMain = class(TForm)
   procedure FormCreate(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 fmMain: TfmMain;

implementation

{$R *.dfm}

procedure TfmMain.FormCreate(Sender: TObject);
var
 IdTCPClient: TIdTCPClient;
 buf: TBytes;
begin
 SetLength(buf, 100);  // Устанавливаем длину пакета.
 buf[0] := 77; // Инициализируем пакет.
 IdTCPClient := TIdTCPClient.Create(Application);
 try
   IdTCPClient.Host := "127.0.0.1";
   IdTCPClient.Port := 777;
   IdTCPClient.Connect;
   IdTCPClient.IOHandler.ReadInteger;
   IdTCPClient.IOHandler.Write(Integer(1));
   IdTCPClient.IOHandler.Write(Integer(Length(buf))); // Отсылаем размер буффера.
   IdTCPClient.IOHandler.Write(buf); // Отсылаем буффер.
   IdTCPClient.Disconnect;
 finally
   IdTCPClient.Free;
 end;
end;

end.

пример на Indy 10, встроенного в BDS2006.


 
Сергей М. ©   (2006-09-12 08:56) [59]


> _Sergey_ ©   (12.09.06 00:17) [53]
> Это компоненты, создающие в неблок. режиме столько подключений,
>  сколько клиентов попытается подключиться. В блок. режиме
> - другое дело.


Дались тебе эти "лишние" подключения !)

Насколько я понял, у тебя одна проблема - ты не в состоянии отладить сервер, работающий одновременно более чем с одним клиентом. Но это же не повод извращаться с ограничением кол-ва клиентов до единицы !

И хоть в блокирующем хоть в неблокирующем режиме все это происходит - нет никакой разницы.


> А еще там св-во есть, MaxConnections называется. Оч. полезное
> св-во


Ничего полезного оно для тебя не представляет. Работатет оно точно так же примитивно - если очередной подключившийся клиент "лишний", для него тут же выполняется дисконнект.


> подскажете, как именно реализуется этот контроль?


см. TServerSocket.ActiveConnections


> программа должна уметь правильно их обработать, оставляя
> за собой способность работать в автоматическом режиме, а
> не ждать нажатия пользователя на кнопку очередного MessageBox-
> а с ошибкой


Вот и обрабатывай их правильно)..  в чем проблема-то ?

По поводу DoS-атак, если они так тебя волнуют, ты уж выбирай - либо настоящий полноценный сервер, реализующий true conditional acceptance, либо его жалкое примитивное подобие, опирающееся на backlog queue size = 1


 
_Sergey_ ©   (2006-09-12 17:05) [60]


> код сервера:

Ээх. Спасибо за пример, но назад я возвращаться не буду.


> Насколько я понял, у тебя одна проблема - ты не в состоянии отладить
> сервер, работающий одновременно более чем с одним клиентом. Но это
> же не повод извращаться с ограничением кол-ва клиентов до единицы !

Может, действительно не в состоянии. Я могу это признать. Я любитель, а не профессионал. Тем более, занимаюсь программированием для сетей 3 месяца с перерывами. Сервер, работающий с 1 client max - это простое решение. И его с головой хватит для моей задачи. В жестких условиях тестирования он себя хорошо показал. В таких условиях, как при тесте, он небудет работать никогда. Тем не менее, и при тесте он справляется. Это не сервер, предназначенный для передачи файлов.

> см. TServerSocket.ActiveConnections

TServerSocket.Socket.ActiveConnections - число законнекченных клиентов
При его превышении я могу только вручную (через св-ва) отконнектить лишних. А это не годится. Лишние клиенты совсем не должны коннектиться.

> либо настоящий полноценный сервер, реализующий ...

Думаю, меня и текущая реализация вполне устраивает. Она имеет запас по производительности и надежность. Защита, правда, минимальна. Но, если мое приложение и будет использоваться, то только в изолированной ЛС, где никто не будет пытаться навредить его работе (подделывать пакеты для отправки, досить, ...). Мои вопросы по реализации безопасности - это вопросы на будущее. С уклоном: авось пригодится; а вдруг придется реализовывать. А пока меня больше волнуют вопросы обеспечения совместмости с HT. Буду пробовать использовать SetThreadAffinityMask
.


 
Eraser ©   (2006-09-12 17:16) [61]

> [60] _Sergey_ ©   (12.09.06 17:05)


> Сервер, работающий с 1 client max - это простое решение.

это, уж извини, туповатое решение. зачем ограничевать количество соединенй?.. ума не приложу...
мало того, что это "решение" уменьшает производительность системы и увеличивает нагрузку на процессор и сеть, оно ещё и трудно реализуемо, в том виде, в котором ты хочешь.. а самое главно - бесполезно.


 
_Sergey_ ©   (2006-09-12 22:11) [62]


> зачем ограничивать количество соединений

Все начинается с малого. Пример: 100 кг груз можно перевести легковой машиной и грузовиком. Но 20 т легковой машиной не перевезти. Когда мне понадобится перевезти 20 т, я возьму грузовик: по моим расчетам мой сервер (теоретически, на основе подсчета числа обслуженных клиентов при стресс-тесте) уже, при одноклиентской реализации, сможет обслужить около 20 тыс. клиентов за примерно 30 мин. на P4. Это идеальные условия. Сбросим 3 тыс. на перепередачу при занятости сервера. И того: 17 тыс. за 30 мин. в ЛС. А если учесть, что каждый из клиентов будет передавать небольшой пакет через примерно 15 мин., получится, что половина из 17 тыс. - это и есть число работающих клиентов (отдельных машин, или задействованных процессоров при использовании многопроцессорных машин [на них запускается столько клиентов, сколько на них установлено процессоров]). И того получается оч. большая цифра: 8 500 клиентов. Такое число клиентов не планируется, и его не будет никогда! Максимум - 10. Вопрос: в чем ограниченность моего мышления? Если и так запас по производительности по теоретическим оценкам превосходит ожидаемое число клиентов в 850 раз. Все просто.


> это "решение" уменьшает производительность системы

Реконнекты клиентов не повышают нагрузку на сервер. Разве что в те несколько секунд реконнектов клиента загружают процессор, на котором работает клиент. И то я в клиенте использую при реконнекте sleep(2000), получается, я не столько загружаю процессор на клиентской стороне, сколько теряю процессорное время на стороне клиента. Но что такое пару секунд по сравнению с 15 минутами?
Тем более, даже в стресс-тесте реконнект клиентов в текущей реализации - единичные случаи. На около 2000 передач от клиентов у меня было 20-50 повторных передач из-за занятости сервера. Могу протестировать еще раз и выслать логи клиента на мыло, если интересно. Думаю, у мнея не самые плохо реализованные логи :) Причем, и серверные тоже могу выслать. Но там будет несколько Мб подобного текста, но все события довольно подробно описаны.

> увеличивает нагрузку на ... сеть

Работать приложение будет в ЛВС. Если и будут повторные передачи, то их будет оч. мало, судя по стресс-тесту. Скорость там достаточная, и небольшим количеством "лишних" маленьких пакетов можно пренебречь, как мне думается.


> трудно реализуемо

Уже реализовал. Благодаря твоей же
подсказке. Как я сразу сам не додумался ввести обратную связь перед передачей, ума не приложу.


> бесполезно

Если еще не убедил, то скажу так. Win 9x плохо переносят многопоточные приложения (заявление из собственного опыта и высказываний людей на разных форумах, в частности, сетевые многопоточные приложения, прекрасно работающие на WinNT, работают и на Win 9x, но периодически "вылетают" с разными сообщениями об ошибках. Это только один из примеров.). Для меня важна совместимость, начиная по крайней мере с W98.
Понятно, что достаточно хотя бы 1 машинки под WinNT, и можно подумать и о
conditional acceptance, и об других, специфичных для WinNT 4.0+ WinSock 2.2 Windows-расширениях ф-ий работы с сокетами. Но могу сказать так:
Если все же производительности сервера мне не будет хватать->если повторных передач будет слишком много->если клиенты будут простаивать долго, то я сделаю так:
вынесу код работы с клиентом (после accept) в отдельную процедуру, защищу код обработки пакетов критической секцией, и буду создавать отдельные потоки на каждое соединение, но ограничу максимальное число потоков, скажем, 30-ю. Таким образом, у меня получится многоклиентский сервер на блокирующих сокетах (не самая удачная реализация, но ее будет довольно). При этом уменьшится время реакции сервера (клиент почти гарантированно будет передавать пакеты сразу), но при зависании хотя бы 1 потока в этом случае и не выхода из критической секции все ост. потоки будут блокированы. Сервер при этом будет в нерабочем состоянии. Время реакции сервера уменьшится, но не увеличится скорость обработки пакетов, поскольку в моей реализации сейчас: если сервер не создает канал связи с очередным клиентом, значит, он в этот момент обрабатывает данные, пришедшие от предыдущего клиента, или принимает эти данные. А все эти процедуры оч. быстрые. Таким образом, выиграш в производительности ожидается мизерный (на основе информации, изложенной выше). Вопрос: а стоит ли гнаться за сомнительными меньше 1% приростами в задачах, когда этот прирост будет проявлять себя лишь при нагрузках, больших в 850 раз, чем планируемые нагрузки?


 
Eraser ©   (2006-09-13 01:43) [63]

> [62] _Sergey_ ©   (12.09.06 22:11)


> Максимум - 10. Вопрос: в чем ограниченность моего мышления?

в этом

> Такое число клиентов не планируется, и его не будет никогда!


> Реконнекты клиентов не повышают нагрузку на сервер.

повышают, установка TCP соединения - сравнительно затратный процесс.

> Уже реализовал. Благодаря твоей же
> подсказке. Как я сразу сам не додумался ввести обратную
> связь перед передачей, ума не приложу.

хм.. а при чем тут обратная связь.. я имел ввиду реализацию полностью однопоточного сервера без дисконнектов, о которых писали тут [59].

> На около 2000 передач от клиентов у меня было 20-50 повторных
> передач из-за занятости сервера.

в масштабах крупного сервера - это очень большой процент потерь, т.е. получается, что при пиковой нагрузке есть очень большой шанс не подключится с первого раза.

> Если еще не убедил, то скажу так. Win 9x плохо переносят
> многопоточные приложения

угу, когда создешь около десятка загруженных потоков - плохо )

> в частности, сетевые многопоточные приложения, прекрасно
> работающие на WinNT, работают и на Win 9x, но периодически
> "вылетают" с разными сообщениями об ошибках

в этом виновата только кривость рук программистов, делающих программы, которые ""вылетают" с разными сообщениями об ошибках".

> Для меня важна совместимость, начиная по крайней мере с
> W98.
> Понятно, что достаточно хотя бы 1 машинки под WinNT, и можно
> подумать и о
> conditional acceptance, и об других, специфичных для WinNT
> 4.0+ WinSock 2.2 Windows-расширениях ф-ий работы с сокетами.

вот то-то и оно, кстати, если уж на то пошло - есть повод задуматься о разных версиях реаизации протокола для разных систем.. реализовать это не так уж сложно.

> Если все же производительности сервера мне не будет хватать-
> >если повторных передач будет слишком много->если клиенты
> будут простаивать долго, то я сделаю так:
> вынесу код работы с клиентом (после accept) в отдельную
> процедуру, защищу код обработки пакетов критической секцией,
> и буду создавать отдельные потоки на каждое соединение,
> но ограничу максимальное число потоков, скажем, 30-ю. Таким
> образом, у меня получится многоклиентский сервер на блокирующих
> сокетах

1.именно так и нужно делать сразу. по крайней мере, мне не понятны причины, почему так не делать.
2. почему именно на блокирующих?
3. все уже сделано до тебя, называется TIdTCPServer :)

> не самая удачная реализация, но ее будет довольно

тоже не понятно почему? собственное умозаключение?

> но при зависании хотя бы 1 потока в этом случае и не выхода
> из критической секции все ост. потоки будут блокированы.

а в твоей реализации не будут? к тому же сам код передачи данных не обязан быть защищен крит. секцией, данные можно считывать в промежуточный локальный буффер, а уже после заполнения этого буффера нужным пакетом, синхронизировать с программой, вот и все.

PS и все таки еще раз посоветую - не изобретай велосипеды, на своем опыте не раз убеждался - неблагодарное это занятие :)


 
Сергей М. ©   (2006-09-13 08:44) [64]


> _Sergey_


Подозреваю, что ты изначально пошер неверной дорогой.

Если речь идет только об ЛВС под управлением Windows, то задача "гарантия доставки + минимизации сетевой нагрузки + максимальная производительность транспорта + ограничение числа одновременно обслуживаемых сервером клиентов" с легкостью решается использованием именованых программных каналов (вместо Winsock).


 
_Sergey_ ©   (2006-09-13 11:41) [65]


> в этом

Это не ограниченность, а реальность.


> я имел ввиду реализацию полностью однопоточного сервера
> без дисконнектов

Правильно. У меня сейчас полностью однопоточный сервер без дисконнектов. Сервер не создает канал обмена данными, пока он обслуживает хотя бы 1-го клиента (для 2-го клиента просто не вызывается accept). И дисконнект он не вызывает для 2-го (N-го) клиента. 2-ой клиент добавляется в очередь на подключение, но поскольку он не получает от сервера разрешения на передачу, то он определяет, что он не первый. И повторяет попытку подключения.


> повышают, установка TCP соединения - сравнительно затратный
> процесс.

Вот как раз на сервер нагрузку и не повышают. Соединение то не устанавливается.


> 1.именно так и нужно делать сразу. по крайней мере, мне
> не понятны причины, почему так не делать.

Потому, что и 1 потока мне достаточно. Незачем создавать лишние потоки, если теоретическая производительность, расчитанная на основании теста, превышает ожидаемую более чем в 800 раз.


> 2. почему именно на блокирующих?

Идеология их мне понравилась. Простота (линейность пргграммы). Да и незачем мне вызывать сетевые ф-ии, чтобы они выполнялись в фоне. Я должен быть уверен, что ф-ия завершилась с каким-то результатом к моменту, когда программа собирается выполнить след. ф-ию или операцию. Тем более, в *NIX системах "родными" являются блокирующие сокеты. Если будет задача перенести все это на сервер, работающий под *NIX, то проблемы почти минимальны - все ф-ии для работы с сетью у меня только стандартные, не используются Windows-расширения. Останется только переписать некоторый дополнительный код, попробывать скомпилировать Kylix или FreePascal (говорят, неплохая совместимость с Delphi). На худой конец, не составит большого труда перевести на C++ под gcc. Но тут уже придется постараться (для меня).


> собственное умозаключение?

Не совсем. "Размножать" и уничтожать потоки - это довольно ресурсоемкий процесс. Поэтому в 1 поток обычно выносится работа с несколькими клиентами. А у меня будет 1 поток = 1 клиент.

"Какой вариант использовать - поток на каждый сокет, либо один поток обрабатывает все соединения - вопрос, к которому нужно подходить по-разному в каждом конкретном случае. Если в процессе общения с клиентом серверу требуется значительное время на подготовку и обработку данных, то, конечно, следует создать разные потоки, чтобы другим клиентам не пришлось ожидать завершения обработки, а работать паралелльно. В противном случае, если обработка минимальна, то создание большого количества процессов окажет влияние в худшую сторону на общую производительность системы." (c)

Теперь у меня есть 1 поток - "кусочек" многопоточного сервера, и мой сервер всегда можно переделать в многопоточный.

Остался вопрос по SetThreadAffinityMask. Если имеется многопоточный сервер, то:
1) Если NT, то определить кол-во установленных процессоров через GetSystemInfo.
2) Для каждого подкл. клиента создавать свой поток, привязывая его SetThreadAffinityMask сначала к 0, след. поток - к 1-му, ... N, затем снова 0-му процессору?


> Подозреваю, что ты изначально пошер неверной дорогой.
>
> Если речь идет только об ЛВС под управлением Windows, то
> задача ...

Почему только под управлением Windows?
http://en.wikipedia.org/wiki/Named_pipe
Pipes - это идеология изначально *NIX-систем, в кот. они используются для коммуникации между процессами.
http://www.kolasc.net.ru/cdo/programmes/os/343.htm

Для того, чтобы связать процессы на разных ПК, нужно создать Named Pipes.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ipc/base/named_pipes.asp
"Windows Me/98/95:  Named pipes cannot be created." (с)
Поэтому этот вариант не подходит.


 
_Sergey_ ©   (2006-09-13 12:04) [66]

И еще один вопрос: как передавать 0-й байт (00h). Ведь при копировании из приемного буфера этот байт расценивается как конец строки? Или его надо заменять на другую комбинацию символов? Но тогда как работают протоколы, основывающиеся на TCP/IP, и передающие бинарные файлы? Ведь в них однозначно встречаются 0-е байты.


 
Сергей М. ©   (2006-09-13 12:33) [67]


> Почему только под управлением Windows?


Потому что это твой случай, судя по перечню ОС в сабже.
В целом ничего не имею против *nix на эту тему.


> "Windows Me/98/95:  Named pipes cannot be created." (с)


Только идиоту придет мысль размещать серьезную серверную логику на маздайной платформе.
Маздай - платформа для рабочих станций, но никак не серверная)


> при копировании из приемного
> буфера этот байт расценивается как конец строки?


КЕМ (или чем) расценивается ?


 
Сергей М. ©   (2006-09-13 12:35) [68]


> как работают протоколы, основывающиеся на TCP/IP, и передающие
> бинарные файлы? Ведь в них однозначно встречаются 0-е байты


так и работают.

Самому TCP-протоколу безразлично содержимое транспортируемых с его помощью данных. Все остальное - право и обязанность прикладных надстроек над TCP.


 
Eraser ©   (2006-09-13 13:52) [69]

> [65] _Sergey_ ©   (13.09.06 11:41)


> Остался вопрос по SetThreadAffinityMask. Если имеется многопоточный
> сервер, то:
> 1) Если NT, то определить кол-во установленных процессоров
> через GetSystemInfo.
> 2) Для каждого подкл. клиента создавать свой поток, привязывая
> его SetThreadAffinityMask сначала к 0, след. поток - к 1-
> му, ... N, затем снова 0-му процессору?

можно так, можно менее экономичный вариант - взять и привязать весь процесс к опр. процессору SetProcessAffinityMask.


 
Сергей М. ©   (2006-09-13 13:59) [70]


> _Sergey_


Нафих тебе, скажи на милость, сдалась SetProcess/ThreadAffinityMask, если ты изначально планируешь однопоточность своего сервера ?


 
GanibalLector ©   (2006-09-13 17:09) [71]

Хм...я,например, сделал сабж.
Каков был подход :
-на сервере при каждом новом клиенте я создаю НОВЫЙ поток, в поток передаю некоторую структуру(в одном из полей структуры присутствует CountThread,т.е. кол-во работающих потоков).
-создавшийся поток первым делом проверяет эту структуру(а именно CountThread) и если он больше 1,то

begin
   ShutDown(Sock,1);
   CloseSocket(Sock);
 end ;

т.е. принудительно оборвать связь с клиентом.
Вот,собственно, и все. Работает сабж на Win98,WinXP.
Код пока не привожу,надо оформить и исправить некоторые ошибки :)


 
_Sergey_ ©   (2006-09-13 20:57) [72]


> Только идиоту придет мысль размещать серьезную серверную
> логику на маздайной платформе.
> Маздай - платформа для рабочих станций, но никак не серверная)

Есть провайдеры и конторы, которые используют Win2003 Server для предоставления разл. услуг. Я не буду спорить по поводу идиотизма такого решения, но это есть. Платформа для рабочих станций - это да. Сам *nix не юзаю. Но признаю его как серьезное семейство ОС, но только в отношении построения на их базе серверов, в плане удобства работы десктопные решения, основывающиеся на *nix недалеко ушли от своих серверных собратьев (ИМХО, можно тут затеять спор, но спорить мне не к чему на эту тему). Куда удобнее Win. Дак вот. ВСЕ машинки, на кот. планируется запускать клиентов, работают именно под Win, т.к. это ПК обычных рядовых пользователей. Не больше, не меньше. И никто не будет там ставить ничто другое. И с LiveCD никто загружаться не будет, как и прерывать свою работу.
Поэтому и клиент, и сервер (не обязательно, можно 1 машинку под платформой NT и найти) должен работать под управлением Win. Причем клиент - обязательно на ВСЕХ версиях Win. Поэтому pipes по постановке задачи не подходят.


> КЕМ (или чем) расценивается ?

Приемные и передающие буфера сокетов - это массивы PChar. Так уж винда сделана. Для копирования из буфера нужно применять ф-ии, работающие с PChar (null-terminated strings) - например, StrLCat я использую для объединения частей данных при recv. Но в null-terminated strings нету в 0-м байте строки, или где-либо еще счетчика кол-ва символов в строке. Конец строки "опознается" по 0-му байту. Вот и получается, что, встретив 0-й байт, ф-ия считает, что данных в буфере нет. А они там есть. Вопрос: как их оттуда "забрать" и "склеить" (append) с уже существующей строкой?


> ... сдалась SetProcess/ThreadAffinityMask, если ты изначально
> планируешь однопоточность своего сервера ?

Это был вопрос, кот. имел своей целью подтвердить/опровергнуть мои догадки по использованию SetThreadAffinityMask. Зачем мне нужно использовать эту ф-ию?

> 5) осталась проблемка: с включенным HT при стресс-тесте
> иногда клиенты вылетают с сообщением об ошибке обращения
> к памяти, адреса все время разные. При выключенном HT такая
> проблема исчезает. Вероятная причина: винда или ее библиотеки
> (включая сетевые) не всегда правильно работает на многопроцессорной
> машинке (процессоры хоть и виртуальные, но их все же формально
> 2 шт.). В старой реализации такая прблема проявлялась раза
> в 4 чаще.



> возможно в данном случае поможет ф-ия SetThreadAffinityMask,
>  которая позволяет "привязать" поток к определенному процессору.
> . не знаю как оно будет работать с HT.. думаю нормально
> )


 
_Sergey_ ©   (2006-09-13 21:04) [73]


> Хм...я,например, сделал сабж.
> Каков был подход :
> -на сервере при каждом новом клиенте я создаю НОВЫЙ поток,
>  в поток передаю некоторую структуру(в одном из полей структуры
> присутствует CountThread,т.е. кол-во работающих потоков).
>
> -создавшийся поток первым делом проверяет эту структуру(а
> именно CountThread) и если он больше 1,то
>
> begin
>    ShutDown(Sock,1);
>    CloseSocket(Sock);
>  end ;
>
> т.е. принудительно оборвать связь с клиентом.
> Вот,собственно, и все. Работает сабж на Win98,WinXP.
> Код пока не привожу,надо оформить и исправить некоторые
> ошибки :)

Спасибо. Я понял Вашу реализацию. Но я уже реализовал сабж. Причем, как я скромно полагаю, более правильным способом: я просто-напросто не вызываю accept для 2-го и последующих клиентов. И отключать мне поэтому некого, т.к. никто лишний и не подключен (сохраняются ресурсы системы, на кот. стоит сервер; да и зачем устанавливать соединение для др. клиентов, если этого и не надо, а затем отключать их?). И оба (сервер и клиент) моих приложения работают под Win 9.x и WinNT. Разве что под Win95 не проверял. Но, подозреваю, что и без обновления до WinSock 2.2 под Win95 тоже будет работать.


 
Eraser ©   (2006-09-13 22:18) [74]

> [72] _Sergey_ ©   (13.09.06 20:57)


> > Только идиоту придет мысль размещать серьезную серверную
>
> > логику на маздайной платформе.
> > Маздай - платформа для рабочих станций, но никак не серверная)
>
>
> Есть провайдеры и конторы, которые используют Win2003 Server
> для предоставления разл. услуг. Я не буду спорить по поводу
> идиотизма такого решения, но это есть.

при чем тут win2k&? маздайная платформа это win95/98/me :)


 
Сергей М. ©   (2006-09-14 08:49) [75]


> Есть провайдеры и конторы, которые используют Win2003 Server
> для предоставления разл. услуг. Я не буду спорить по поводу
> идиотизма такого решения, но это есть


"Маздаем" принято обзывать линейку ОС Win9x/Me.


> Приемные и передающие буфера сокетов - это массивы PChar.
>  Так уж винда сделана. Для копирования из буфера нужно применять
> ф-ии, работающие с PChar (null-terminated strings)


Ох и ересь ты несешь)


 
_Sergey_ ©   (2006-09-14 13:42) [76]


> Ох и ересь ты несешь)

Прочитал в книге. Если ересь, то поправьте меня, и скажите, как правильно, если не сложно конечно. Но у меня есть такая проблема, и мне нужно найти ее решение. В частности, можно применять массив char, и вручную копировать столько символов, сколько вернет recv. Но, как известно, некот. ф-ии работы со строками написаны на asm, и поэтому более быстродействующие. Поэтому предпочтительнее не копировать строки посимвольно, а применять ф-ии для работы со строками. Неужели я и в этом неправ? ;) Или, в условиях большой производительности современных ПК не имеет значения, применеяется ф-ия, написанная на чистом asm, или на языке высокого уровня?


 
Сергей М. ©   (2006-09-14 13:59) [77]


> _Sergey_ ©   (14.09.06 13:42) [76]


Чем дальше в лес, тем больше дров)
Начали за здравие - ограничение числа одновременно обслуживаемых клиентов, а продолжили за упокой - работа со строковыми данными.

Ну никак не связаны эти две темы !

Ну хорошо, поговорим "за упокой" ..
Вот ты вызвал recv(), прочитал N байт в указанный буфер. Ну и делай с ними все что душе угодно ! Хоть как строковые данные интерпретируй их, хоть как двоичные, хоть с asm, хоть без asm - winsock"у это абсолютно фиолетово, это уже прикладной уровень.


> можно применять массив char, и вручную копировать столько
> символов, сколько вернет recv


Да что хочешь, то и применяй)
К winsock это, повторяю, не имеет никакого отношения.
Буфер м.б. любого типа - хоть char, хоть byte, хоть что угодно...
Имея в буфере некие данные, ты волен трактовать их содержимое так как этого требует логика программы.


 
_Sergey_ ©   (2006-09-14 22:22) [78]

Все понятно. Как протестирую реализацию со SetThreadAffinityMask - напишу про результаты.


 
_Sergey_ ©   (2006-09-15 22:13) [79]

Использование SetThreadAffinityMask не помогло. Привязал всех клиентов на машинке с P4 3.0 GHz HT к 0-му процессору командой SetThreadAffinityMask(GetCurrentThread, 1). ОС - WinXP Pro SP2. При этом при включенном HT, запущенных 39 клиентах и 1-м сервере с периодичностью в 15 мин. клиенты "вываливаются" с MessageBox-ами с сообщениями об ошибках работы с памятью, причем с разными адресами. Примеры:
;-------
Инструкция по адресу "0x00140190" обратилась к памяти по адресу "0x98449844". Память не может быть "written".
"OK" -- завершение приложения
;-------
Инструкция по адресу "0x77f745cc" обратилась к памяти по адресу "0xffffffff". Память не может быть "read". "OK" -- завершение приложения
;-------
Инструкция по адресу "0x00140199" обратилась к памяти по адресу "0x00002930". Память не может быть "written".
"OK" -- завершение приложения
;-------
Инструкция по адресу "0x77f745cc" обратилась к памяти по адресу "0x00000007". Память не может быть "written".
"OK" -- завершение приложения
;-------
Инструкция по адресу "0x00000000" обратилась к памяти по адресу "0x00000000". Память не может быть "read". "OK" -- завершение приложения
;-------
Причем частота появления ошибок увеличивается при активном параллельном использовании "тяжелых" сторонних программ во время проведения теста (Photoshop, FineReader, ...), особенно при их запуске/завершении.
Дополнительная информация: В своих программах использую такие юниты: SysUtils, WinSock, Windows, Classes. Перезагружаю машинку, выключаю в BIOS-е HT, провожу тот же тест - никаких сообщений об ошибках. Все чисто. Что посоветуете, какие мысли по поводу вышеизложенного?


 
Eraser ©   (2006-09-15 23:00) [80]

> [79] _Sergey_ ©   (15.09.06 22:13)

ну что ж.. скорее всего ошибка в 17 строке, как говорится.. просто на процессоре с HT, вероятность её возникновения больше.



Страницы: 1 2 3 вся ветка

Форум: "Сети";
Текущий архив: 2007.02.25;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.75 MB
Время: 0.058 c
15-1170252125
Sergey13
2007-01-31 17:02
2007.02.25
Участников интернет-форума судят "за оскорбления властей"


15-1170170111
Самовар
2007-01-30 18:15
2007.02.25
Опять ДНС :-((


2-1170872689
Ламерок
2007-02-07 21:24
2007.02.25
Как правильно сделать ?


15-1170135796
DeadMeat
2007-01-30 08:43
2007.02.25
Пиратов наказали


15-1170341727
malyar
2007-02-01 17:55
2007.02.25
редактор для PHP





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский