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

Вниз

Новый вопрос по сокетам :-)   Найти похожие ветки 

 
Fredericco   (2002-04-09 11:53) [0]

Ситуация следущая. Есть сервер, который может соединять клиентов по 10 портам. Пока порты закрыты. Новый клиент посылает запрос на сервер по служебному порту, скажем 11. Сервер возращает клиенту номер свободного порта, например 1. Клиент соединяется по порту 1 и спокойно себе работает. Второй клиент аногогичным способом соединяется на 2 и так далее. Фишка в том, что каждому клиенту свой порт. Но вдруг первый клиент отсоединяется. На сервере я должен закрыть 1 порт и пометиь в программе что он свободный, и когда придет третий клиент, по служебному порту отправит запрос то получит ответ, что свободный порт 1 и подключится к серверу для дальнейшей работы по 1 порту. Так вот в процедуре обработки события я пишу следующее:

procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Порт по которому произошел дисконнект.Close;
end;

Генерируется ошибка :-(. И самое интересное. Если после дисконекта я в ручную закрою порт так:

procedure TForm1.Button3Click(Sender: TObject);
begin
Порт по которому произошел дисконнект.Close;
end;

То все ОК. Не подскажете что не так?


 
Digitman   (2002-04-09 12:37) [1]

1. "Каждому клиенту - отдельный порт сервера"
Совершенно неразумно. И неверно как минимум концептуально. За каким, спрашивается, нужно иметь статически занятый служебный порт да еще и кучу динамически распределяемых портов ? Что, на одном порту нельзя делать все, что тебе нужно ? Если разные группы клиентов должны автоматически получать строго определенные сервисы (в зависимости от группы, например), то это еще как-то оправдано, но, если протокол един для всех - нонсенс полный ...

2. В обработчике OnClientDisconnect() нет нужды (и концептуально неверно) явно закрывать гнездо, ассоциированное с клиентом - TServerWinSocket сделает это самостоятельно и автоматически сразу по завершению обработчика. Сим событием сервер лишь извещает тебя об этом факте и не более того. И уж тем более неверно изменять св-во TServerSocket.Active в этом обработчике (как, впрочем, и в обработчиках любых других событий объекта TServerSocket). Делай в обработчике все, что угодно, но не изменяй св-ва объекта TServerSocket и св-ва объекта TCustomWinSocket, ассоциированного с тек.соединением


 
Fredericco   (2002-04-09 12:51) [2]

Digitman >> "Каждому клиенту - отдельный порт сервера" не моя идея, а начальства. На каждом порту будет висеть по драйверу. Драйверы же для устройств, которые очень не похожи друг на друга. А если я не как не буду закрывать порт от которого отдисконнектился клиент, то злобный хакер напишет:

ClientSocket1.Port:=Свободный порт на сервере и готовый к приему;
ClientSocket1.Open;
ClientSocket1.Socket.SendText("ВИРУС");

И что делать?


 
Wonder   (2002-04-09 13:19) [3]

"не моя идея, а начальства."
А реализовывать эту "идею" ведь ты будешь? Ну и флаг тебе в руки - разъясни начальству, что так делать неразумно и неправильно.

"А если я не как не буду закрывать порт от которого отдисконнектился клиент, то злобный хакер напишет:
...
И что делать?"


Опять-таки, ну реализуй ты на сервере проверку на правильность принимаемых данных, чтобы никакие "ВИРУС" не прошли. Ведь сам же делаешь! Ты что - все принятые данные без разбора пытаешься обрабатывать? Придумай а-ля протокол обмена какой-нибудь свой, фильтруй соединения по адресу клиента, включи в программу механизм авторизации, наконец.
Масса вариантов...


 
Digitman   (2002-04-09 13:24) [4]

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

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


 
Fredericco   (2002-04-09 13:32) [5]

Digitman >> Ты прав и Wonder тоже. У меня все заработало, только вот что. Хакер лезет ко мне по 1001 порту. Я вижу, что он мне присылает и Socket.Close верно? Только вот вместе с хакером у меня и все нормальные клиенты тоже "refuse" -(


 
Digitman   (2002-04-09 13:43) [6]

>Fredericco
Это почему же ?
Ты вообще-то представляешь разницу между TServerWinSocket.Close и TServerClientWinSocket.Close ? Close-метод объекта какого конкретно класса ты вызывать будешь ?


 
Kaban   (2002-04-09 13:47) [7]

Почему все то клиенты отключатся. Делаешь:

procedure TALMC128Server.ServerSocketClientConnect(Sender: TObject; Socket: TCustomWinSocket);
begin
if not CheckIP(Socket.RemoteAddress) then Socket.Close;
end;

Отключается только тот клиент, который только что пытался подсоединиться


 
Fredericco   (2002-04-09 15:25) [8]

Kaban >> Они все с одного компьютера. Но это уже не важно. Начальству было доказано что с одним портом лучше и оно согласилось. УРРРРА!!!!


 
Digitman   (2002-04-09 15:52) [9]

>Fredericco
Любопытно-таки было бы узнать, какие же веские контраргументы ты привел "начальству", коль оно так скоро изменило свое концептуальное мнение по сабжу)


 
Fredericco   (2002-04-10 10:20) [10]

Digitman >> Начальство знакомо токлько с VB и Visio C++. Там компонент для работы с сокетами только WinSock. В Дельфи он в принципе тоже есть, но я об этом узнал только вчера, а до этого, как сам понимаешь, работал только с TServerSocket/TClientSocket. Так вот, у WinSock довольно скудные возможности, в следствии чего начальство просто не подозревало, что по одному порту можно нескольких клиентов сажать :-) Слушай, у меня теперь еще один вопрос назрел :-) Когда у меня происходит новое соединеие, я для внутренней идентификации запоминаю Socket.SocketHandle, правильно делаю? И если правильно, то когда я хочу именно этому соединению текст отпрвить мне нужно среди всех Socket.Connectios[i].SocketHandle искать нужный мне Хэндл и ему отправлять? Верный ли алгоритм?


 
Digitman   (2002-04-10 11:08) [11]

>Fredericco

Верно, но зачем ? Если, имея хэндл гнезда, ты хочешь обращаться непосредственно к WinsockAPI, например, с целью изменения некоторых гнездовых опций (которые недоступны в классе TCustomSocket), тогда еще это имеет смысл. В большинстве же случаев все базовые Winsock-ф-ции управления гнездом (прием, передача, ожидание событий и пр.) инкапсулированы в классах TCustomSocket/TCustomWinSocket, и нет никакой необходимости "лезть в их потроха" - достаточно иметь ссылку на объект класса TCustomWinSocket (возвращаемый, к примеру, по Socket.Connectios[..]), чтобы управлять гнездом ничуть не худшим образом


 
Fredericco   (2002-04-10 13:32) [12]

Digitman >> Понял. Спасибо! Но у меня проблема {опять 25}. Подключаются к серверу по одному порту не более 43 клиентов. Когда подключаю 44 - пишет - Win Socket Error 10055 on API "connect" Это нормально?


 
Digitman   (2002-04-10 14:04) [13]

Для ответа на этот вопрос, imho, непосредственно перед созданием гнезда необходимо получить инф-цию о макс.возможном числе гнезд, которые могут быть созданы в контексте сессии ОС.

Такая инф-ция может быть получена вызовом ф-ции Winsock.WSAStartup(), при успешном завершении которой структура WSAData (указатель на которую д.б. передан параметром в WSAStartup) будет заполнена некоторой инф-цией о подсистеме Winsock. Полученное значение поля WSAData.iMaxSockets - это то, что тебе нужно для сравнения с "сакраментальным" числом 43.



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

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

Наверх




Память: 0.48 MB
Время: 0.005 c
1-65046
koty
2002-06-10 08:45
2002.06.20
Печать из RichEdit a или Memo


3-64899
g maxim
2002-05-29 13:45
2002.06.20
Вопрос по PARADOX


1-65070
KIG_S
2002-06-10 13:10
2002.06.20
Каким образом в ListBox-e можно менять местами item-ы


3-64935
bigmel
2002-05-27 11:57
2002.06.20
Подскажите, как в DbGrid обращаться к конкретным рядам?


1-65043
kito
2002-06-10 08:46
2002.06.20
Как правильно скрыть приложение ?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский