![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
сокеты и web service [D6, Win2k]
Lesorub © (2006-11-16 18:34:00)Вот у меня в сетке есть web-сервер (апач на winnt). Хотелось бы чтобы web service на нем, при обращении клиента, брал с другого сервера в сетке (где БД) данные. Для этого я попробовал использовать ClientSocket поместив его в Web-module web service 'а, как это делается в обычных приложениях. Компиляция прошла без проблем, но при запросе программки-клиента, когда происходило событие ClientSocket.Open, выскочила ошибка Access Violation at address такого-то in module таком-то. Read of address такой-то. И информации толком нигде нет по этой теме, в общем, плз, very need help )
Lesorub (2006-11-25 11:21:00) [1]Читал много. Размышлял.
В общем, действительно это глупость использовать задержку. Совершенно согласен теперь с тем, что, в случае асинхронных сокетов, надо писать класс с эвентами, чтобы обрабатывать те самые оконные сообщения, либо использовать синхронные. Сначала пробую использовать синхронные. Причем решил не использовать vcl, а использовать api-функции winsock, поскольку в этом случае приложение как-то более контролируемо.
Делаю подготовку так:
if wsastartup($101,vwsadata)<>0 then halt(1);
vsocket := socket(af_inet,sock_stream,ipproto_ip); //создается сокет
if vsocket = invalid_socket then halt(1);
fillchar(vsockaddr,sizeof(tsockaddr),0);
vsockaddr.sin_family := af_inet;
vsockaddr.sin_port := htons(cport);
vsockaddr.sin_addr.s_addr := inet_addr(ip);
if connect(vsocket,vsockaddr,sizeof(tsockaddr)) = socket_error then halt(1);
//затем отсылаем данные
send(vsocket,buf[1],length(buf),0);
//затем надо принять ответ
recv(vsocket,chresp,1,0);
То есть хочу считывать по одному байту, и с этой целью надо поместить recv в цикл. И вот тут как определить сколько данных пришло в сокет?
А так вроде работает. Как думаете, правильно так делать?
MikePetrichenko (2006-11-20 10:03:00) [2]
> НО! Теперь пишет, после того как поставил паузу, ошибку
> показывает такую: InternalServerError (500)
Правильно пишет.
Вообще это идиотизм, использовать асинхронные сокеты с процедурой задержки, уж простите.
Пользуй либо синхронные, либо события OnConnect OnDisconnet.
P.S. В дельфе асинхронная работа сокетов сделана на основе оконных сообщений (что ни есть гуд для CGI). Следствие. Пиши ручками с использование Event, либо пользуй синхронные, либо события.
Сергей М. (2006-11-20 08:10:00) [3]
> Lesorub © (19.11.06 20:52) [41]
Не надо сокету давать никакую "паузу".
Либо установи ctBlocking, либо органигуй цикл ожидания/выборки/диспетчеризации оконных сообщений.
Lesorub (2006-11-19 20:52:00) [4]хм, но что же тогда, почему же ошибка возникает когда сокету дается время (пауза 10 сек) на открытие
Anatoly Podgoretsky (2006-11-19 20:32:00) [5]> Lesorub (19.11.2006 20:22:39) [39]
Думаем, что нет, поскольку cgi это обычное консольное приложение
Lesorub (2006-11-19 20:22:00) [6]а может запрещено winsock.dll исользовать в cgi, как думаете?
Lesorub (2006-11-19 13:52:00) [7]Код процедуры "пауза" без ошибок
Lesorub (2006-11-19 13:29:00) [8]ага, но откуда!
Anatoly Podgoretsky (2006-11-19 13:05:00) [9]> Lesorub (19.11.2006 11:46:35) [35]
Так у тебя ошибка в сервисе.
Lesorub (2006-11-19 11:46:00) [10]НО! Теперь пишет, после того как поставил паузу, ошибку показывает такую: InternalServerError (500)
Lesorub (2006-11-19 11:39:00) [11]Кстати, теперь после S.Open делаю паузу 10 секунд с помощью Application.ProcessMessages и цикла. Неужели 10 секунд не хватает чтобы перейти S.Active в true !
Lesorub (2006-11-19 11:30:00) [12]Ок, надо почитать :-)
MikePetrichenko (2006-11-19 11:28:00) [13]Тогда он практически НИКОГДА не будет сразу Active = True. Читай про Overlapped IO и Thread blocking sockets.
Думай. И будет тебе просветление.
Lesorub (2006-11-19 11:23:00) [14]non blocked, в асинхронном режиме
пишу так:
S.ClientType:=ctNonBlocking;
MikePetrichenko (2006-11-19 11:20:00) [15]
> хм, может ему какое-то время надо на открытие
Сокет Blocked или Non Blocked?
Lesorub (2006-11-19 10:15:00) [16]хм, может ему какое-то время надо на открытие
Lesorub (2006-11-19 10:08:00) [17]теперь то что ему не хватает
Lesorub (2006-11-19 10:08:00) [18]ага, но без этих строчек
S.Close;
S.Free;
все равно то же самое...
после S.Open пишу
if S.Active=true then Conn:='active'
else Conn:='not active';
а потом наблюдаю за переменной Conn - 'not active', вот ведь как.
MikePetrichenko (2006-11-19 09:59:00) [19]
> S.Open;
> S.Close;
> S.Free;
Так ты же его сразу закрываешь.
Lesorub (2006-11-19 09:55:00) [20]Вот, теперь делаю так:
var
S: TClientSocket;
...
//создаем
S:=TClientSocket.Create(self);
S.Address:='127.0.0.1';
S.Port:=80;
S.Open;
S.Close;
S.Free;
Достижение, обращение клиента проходит нормально. Но зато другая появилась проблема - при открытии сокета свойство Active не переходит в true, даже если явно указать после S.Open строку S.Active:=true.