Форум: "Сети";
Текущий архив: 2002.09.09;
Скачать: [xml.tar.bz2];
ВнизSocket-ы Найти похожие ветки
← →
SDomsk (2002-07-02 15:04) [0]Подскажите, пожалуйста, как в Delphi воспользоваться функциями getsockopt setsockopt? Мне не понятно, каким образом задается определенное значение для опции (в частности для отправки широковещательного сообщения). Зачем 4-й параметр этих функций имеет тип PChar?
← →
Digitman (2002-07-02 15:43) [1]рассматривай 4-й параметр не как PChar, а как просто Pointer, т.е. указатель на буфер, из которого SetSockOpt() берет новое значение опции для задания ее гнезду, или в который GetSockOpt() считывает тек.значение опции.
5-й параметр - размер этого буфера. Различные опции имеют различный размер значения. Например, размер буфера для опций типа DWORD должен быть 4 байта (sizeof(DWORD) = 4).
Пример :
var
OldOption, NewOption: Integer;
OptLen: Integer;
..
OptLen := SizeOf(Option);
GetSockOpt(hSocket, SOL_SOCKET, SO_BROADCAST, @OldOption, @OptLen);
NewOption := Integer(True);
SetSockOpt(hSocket, SOL_SOCKET, SO_BROADCAST, @NewOption, OptLen);
← →
SDomsk (2002-07-03 11:43) [2]Все равно не понятно, дело в том, что когда я пытаюсь установить в GetSockOpt() последний параметр указателем, то машина матерится и не хочет мне компилировать, резонно заявляя то, что наблюдается несоответствие параметров.
Как я понял, информация значении опции (конкретной SO_BROADCAST, которая имеет тип Boolean, или вернее, BOOL), заносится в память по указателю (в нашем примере) @OldOption, а ее длина (этой опции) должна передаваться в переменную OptLen. Или как?
А вот касательно SetSockOpt(), непонятно, почему мы используем NewOption, которая имеет тип Integer, хотя та опция, которую мы устанавливаем, имеет тип BOOL, и, соответственно, ее размер должен быть SizeOf(True)=2?
Пожалуйста, объясните по подробнее насчет этих неясностей.
← →
Digitman (2002-07-03 12:12) [3]Вот декларации :
Winsock.pas
function getsockopt(s: TSocket; level, optname: Integer; optval: PChar; var optlen: Integer): Integer; stdcall;
function setsockopt(s: TSocket; level, optname: Integer; optval: PChar;
optlen: Integer): Integer; stdcall;
Да, разумеется, при такой декларации (что имеется в Winsock.pas) следует делать не
GetSockOpt(..., @OptLen);
а просто
GetSockOpt(..., OptLen);
Я не пользуюсь стандартным Winsock.pas, поэтому и привел ошибочный (для станд.декларации от Борланда) код, вызвавший у тебя недоразумениею
По поводу BOOL.
1.Читай и вникай во фрагмент хэлпа к SetSockOpt():
There are two types of socket options: Boolean options that enable or disable a feature or behavior, and options which require an integer value or structure. To enable a Boolean option, optval points to a nonzero integer. To disable the option optval points to an integer equal to zero. optlen should be equal to sizeof(int) for Boolean options . For other options, optval points to the an integer or structure that contains the desired value for the option, and optlen is the length of the integer or structure.
2.
А вот сюда нужно было залезть в первую очередь для самостоятельного прояснения непонятной ситуации :
Windows.pas
BOOL = LongBool;
LongBool - станд. тип OP, соответствует 4-байтному представлению лон.значения; тот же Win32 Integer-тип по размеру, если угодно
← →
SDomsk (2002-07-03 13:12) [4]Насчет LongBool все учел, записал следущее:
var OldOption, NewOption, OptLen: Integer;
AddrSockCl: Sockaddr_in;
SockDeskrCl: Integer;
........
GetSockOpt(SockDeskrCl, SOL_SOCKET, SO_BROADCAST, @OldOption, OptLen);
и при проверке значения OptLen получаю 0. Интересно, почему? Ведь должно быть 4?
Далее пытаюсь изменить эту опцию:
NewOption :=Integer(True);
SetSockOpt(SockDeskrCl, SOL_SOCKET, SO_BROADCAST, @NewOption, 4);
и при проверке получаю после GetSockOpt() такую же картину, причем сервер этого широковещательного сообщения как не получал, так и не получает.
Может что не так делаю.
Создание сокета описывается следующим образом:
SockDeskrCl:=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
AddrSockCl.sin_family:=PF_INET;
AddrSockCl.sin_addr.S_addr:=INADDR_ANY
AddrSockCl.sin_port:=htons(SERVER_PORT);
if bind(SockDeskrCl,AddrSockCl,SizeOf(AddrSockCl))<>0 then сlosesocket(SockDeskr);
← →
Digitman (2002-07-03 13:45) [5]1. А где анализ результата, возвращаемого Get/SetSockOpt() ? Он что, Пушкину адресован, не тебе ? Где GetLastError() сразу же за вызовом этих ф-ций ?
2. Непонятно - ты что, собственно, хочешь реализовать ? Разрешить данному гнезду передачу broadcast-сообщений или их прием ? И причем здесь сервер , кстати ? Бродкаст как таковой не имеет отношения к этому : режим бродкаста может быть включен и использован для любого гнезда, инициализированного для работы как SOCK_DGRAM.
3. Не уверен, но эту опцию следует, скорее всего, включать до bind()
4. Это весь код ? А где WSAStartup() ? Или он подразумевается ранее ? И где - ОПЯТЬ ЖЕ ! - анализ результата вызова socket() ? Если перед socket() не вызывался WSAStartup(), то socket() обязательно даст отказ ! И последующие вызовы, ссылающиеся на якобы полученный результатом вызова socket() хэндл нового гнезда, попросту бессмысленны !
Проясни все это дело..
← →
SDomsk (2002-07-03 16:24) [6]Задача такая: мне необходимо сделать сервер и клиентов, которые будут запускаться на разных машинах для того, чтобы использовать их ресурсы и производить очень большие расчеты. Все расчетные процедуры написаны, осталось только сделать так, чтобы эти машины-клиенты автоматически кидали широковещательный пакет, чтобы сообщить серверу о том, что он тоже может подключиться к расчету и принять на себя задачу с новыми параметрами.
Я это все попробовал сделать со стандартными компонентами Delphi-ей, у меня все пошло, кроме одного: я никак не могу отправить и ,соответственно, принять это широковещательное сообщение своему серваку, чтобы уже тот из этого сообщения узнал IP клиента и начал с ним работать.
Мне посоветовали работать непосредственно с Winsock. Только я никак не могу достать нормального Help-а, в котором все бы для PASCAL-я было бы расписано. А то руководство, которое есть в Delphi, так оно, как я понял, написано для C++ (может я, конечно и ошибаюсь, но примеры уж точно для него).
Вот такая, вообщето, не очень сложная проблема, если разобраться толком. Я вот, например не знал, что надо вызывать фунуцию WSAStartup() перед созданием сокета. Да и ее толком не понял, как использовать, так как первый входной параметр требует версию Winsock в виде Word, а как этот номер должен быть записан туда и в каком виде, не понятно, толи первый байт одно число версии, а второе - другое, толи иначе, и как эту версию узнать?
Может у кого есть нормальный Help, а еще луше какой нибудь скелет кода, который это все бы обеспечивал, или хотя бы последовательность действий, которые необходимо выполнить, чтобы это все пошло.
Заранее спасибо.
← →
Digitman (2002-07-03 16:46) [7]1. Совершенно непонятно - на кой черт в данной задаче именно UDP-broadcast ? Зачем , спрашивается, прочие клиенты в сети должны "слушать" весь этот broadcast-"шум", если его содержимое адресовано только некоему узлу-"серверу", который, как я понял, собственно и есть единственный, кто должен реагировать на такие сообщения и по факту выполнять что-то ?
2. С чего ты взял, что IP отправителя недоступен адресату, если используются станд. сетевые компоненты Делфи ? На основании чего ты принял такое решение ?
3. Ты что-нибудь слышал о трассировке кода в режиме отладки ? Ты в курсе, что практически все компоненты из состава станд. сетевых компонентов Делфи (палитра Internet) реализованы в модуле ScktComp.pas ? Ты знаешь, что все компоненты - в той или иной мере не более чем оболочка того или иного API ? В т.ч. - WinsockAPI в дан.случае ? У тебя никогда не возникало желание посмотреть (предже чем изобретать велосипед) - КАК ЖЕ САМ БОРЛАНД ДЕЛАЕТ ЭТО ? И делает ли вообще ?
← →
SDomsk (2002-07-03 17:16) [8]1. Насчет IP я не пояснил. На самом деле он не известен клиенту, так как сервер может быть запущен с разных машин. Вот для этого то мне и необходим широковещательный пакет.
2. Теперь я глянул в ScktComp и практически во всем разобрался.
3. Ребята, а в частности, Digitman, зачем так пренебрежительно отвечать на вопросы, ведь, я так думаю, они когда-то возникали и у вас. Поставьте себя на место того, кто его задает. Да в следующий раз и желания большого не будет сюда писать. А вдруг тебя обзовут тупицей из-за того, что другой давно уже понял. Более того, я думаю, что никто никого на самом деле и не заставляет отвечать. Ну считаете вопрос глупым, пропустите его. А с барского плеча-то незачем. Это уже просто некрасиво.
← →
Digitman (2002-07-03 18:01) [9]>SDomsk
Кто тебя, сударь, "тупицей" назвал ? Чего ты выдумываешь ? Какого еще "барского плеча" ? Чего ты несешь ?
Я прошел этот путь с "нуля" ! И искренне пытаюсь направить тебя по тому же пути ! Потому что знаю по себе :чужой опыт - бесценен ! И не надо воспринимать это в штыки !
Ты полез в дебри API, не имея (на поверку) базовых навыков поиска и анализа информации. Какого черта ты возмущаешься тогда ? Я пытаюсь выяснить уровень твоей подготовки, дабы дать тебе наиболее точную (насколько это возможно) рекомендацию, что и как делать при данной постановке задачи. И задал тебе вполне конкретные вопросы, чтобы составить представление о том, с чего начать ...
← →
SDomsk (2002-07-04 11:01) [10]Искренне извиняюсь, если тебя обидел своим подозрением на такое пренебрежение.
По большому счету я сейчас нахожусь именно на том этапе, который ты назвал "нулем". Правда, все-таки кое-чего добился, но вот именно по работе с Winsock возникли некоторые сложности в понимании, связанные, наверняка, именно с непониманием именно этих базовых навыков API.
Буду рад "услышать" рекомендации по этому поводу, если желание еще не пропало.
← →
Digitman (2002-07-04 11:15) [11]В таком случае "вернемся к нашим баранам".
Итак, каковы твои аргументы в пользу отказа от стандартных компонентов TServerSocket и TClientSocket ?
Изложи подробно.
← →
SDomsk (2002-07-04 12:57) [12]Понимаешь, смысл в том, что я не знаю, как с помощью этих компонент послать широковещательное сообщение. То есть, зная конкретный IP сервера, мне, конечно, несложно подключить клиента к нему клиента и там уже делай что хочешь. А когда возник вопрос, как мне автоматически не зависемо от того, где запускается сервер, приконнектить к нему клиентов, тут я уперся в то, что не знаю, как это сделать. Мне тут посоветовали посылать широковещательный запрос устанавливая IP в 255.255.255.255 (ну или x.x.x.255), да только это не помогло. Один мой неуловимый знакомый все это делал через Winsock API, да только единственное, что он мне успел посоветовать, так это работать именно конкретно с функциями из этой библиотеки, что там все это есть. Вот и приходится в этом разбираться с "0"-ля.
Ну а если действительно есть способ, который реализует поставленную задачу именно при помощи этих стандартных компонентов TServerSocket и TClientSocket, то новый велосипед я заброшу в сторону и воспользуюсь проверенным старым.
← →
Digitman (2002-07-04 17:31) [13]Вообще говоря, концептуально неверно, когда "сервер гоняется за клиентом". Пусть даже и в лок.сети. Это задача клиента - найти сервер, задача же сервера - стартовать и "слушать" на заранее известном всем его потенциальным клиентам порту.
Хорошо. Если уж тебя заботит такая задача, то что мешает последовательно пропинговать все потенциально доступные IP-адреса подсети и попытаться для каждого активного IP-адреса подключиться к этому порту ? И , в случае отказа, продолжить сканирование подсети до тех пор, пока подключение не будет успешным либо не будут перебраны все адреса из исх.диапазона ? Это вполне можно реализовать на клиенте, и достаточно просто. И бродкаст никакой не нужен при этом.
Можно поступить и по иному. Каждый клиент в подсети "слушает" на известном серверу порту. Сервер при активизации делает то же самое - сканирует подсеть в попытке коннекта к "слушающему" порту всех потенциальных клиентов, в случае обнаружения коннекта послать некую инф-цию типа "я - сервер, я активизировался и слушаю на таком-то порту". В момент такого коннекта клиент уже будет знать IP-адрес сервера.
А теперь поясни, чем не устраивают вышеупомянутые компоненты с т.з. вот такого решения задачи.
TServerSocket "умеет слушать" и определять адрес подключившегося клиента, TClientSocket "умеет" делать коннект к "слушающему" серверу и обрабатывать ошибки отсутствия сервера на заданном порту по указанному адресу/имени хоста. Любое приложение - и клиентское и серверное - вправе и может использовать как TServerSocket , так и TClientSocket (в нужном количестве) для разных целей, в т.ч. и для целей сканирования.
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2002.09.09;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.011 c