![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
странная проблема с сокетами: [D1, D2, D3, D4, D5, D6, D7, Win95/98, WinME, NT4, Win2k, WinXP]
GroZ © (2004-05-20 11:53:00)Deiphi 5
Нужно с помощью клиент-сокетов конестится к нескольким серверам (на каждый сервер соответственно по клиент-сокету) т.е. есть массив клиент-сокетов. Пытаюсь сделать это следующим образом:
без переделок:
for i := 0 to Length(PrmConns)-1 do begin
if not PrmConns[i].ClientSocket.Active and not PrmConns[i].Connecting then begin
PrmConns[i].ClientSocket.Close;
PrmConns[i].Connecting := true;
PrmConns[i].ClientSocket.Port := PrmConns[i].CurrPort;
PrmConns[i].ClientSocket.Address := PrmConns[i].IP;
PrmConns[i].ClientSocket.Open;
end;
if PrmConns[i].ClientSocket.Active and PrmConns[i].Connecting then begin
PrmConns[i].Connecting := False;
end;
end;
Если сервер запущен, то всё хорошо работает ... но в противном случае (если сервер не запущен) через несколько часов работы Окна маразмятся ... что-то происходт с сетевым сервисом: перестаёт работать инет, не работает Outlook Express (не может приконнектится к серверу) правда по локалке на Sharing можно зайти ...
Выше приведённый код запускается в Timer-e, каждые 800 мс ..
Также в обработчике ошибки клиент-сокета (ClientSocket.OnError):
PrmConns[i].Connecting := False;
PrmConns[i].ClientSocket.Active := False;
PrmConns[i].CurrPort := PrmConns[i].CurrPort + 1;
if (PrmConns[i].CurrPort < PrmConns[i].Port.s) or (PrmConns[i].CurrPort > PrmConns[i].Port.e) then PrmConns[i].CurrPort := PrmConns[i].Port.s;
ErrorCode := 0;
Создаю клиент-сокет так:
procedure TMyClass.CreateClientSocket(var ClientSocket: TClientSocket);
begin
ClientSocket := TClientSocket.Create(Application);
ClientSocket.OnError := ClientSocketError;
ClientSocket.OnRead := ReadSocket;
ClientSocket.OnConnect := ClientSocketConnected;
end;
Если у Вас есть какие-нибудь предложения исправления или предположения причины ошибки - буду очень благодарен если поделитесь ими со мной :)
apihelp (2004-05-23 11:41:00) [1]Проверяй по одному в отдельных потоках. И используй TStringList.values['n'] = 'no'; Ну и таймер+процедура чтоб лист сканила на состояние сокетов. на ком.коннекта except+case
Хотя может не понял суть вопроса.
Digitman (2004-05-21 17:29:00) [2]
> GroZ (21.05.04 17:17) [27]
да будет тебе известно, красавец ты наш, LMD ты наш, что "закрывает сокет" - понятие растяжимое, !
методы TClientSocket.Close и TClientSocket.Socket.Close - методы РАЗНЫХ объектов , выполняются по РАЗНЫМ алгоритмам и каждый из ожидает и/или требует своего вызова в РАЗНЫХ условиях !
а ну марш бегом в исходники !!!
GroZ (2004-05-21 17:17:00) [3]Удалено модератором
Примечание: Поумерь пыл... И бегом читать правила поведения на форуме...
Digitman (2004-05-21 16:38:00) [4]
> GroZ (21.05.04 16:24) [25]
"по кочану" - ответ, думаю, устроит ?
исходники компонента в связи с возникшей проблемой ты не хочешь изучать , выполнять рекомендации в [1] ты не хочешь, прислушаться к [9] ты тоже не желаешь ... что остается ? только "по кочану" ! ... Слепо следуй инструкциям - и да получишь ожидаемый рез-т !
И гонор свой в [6] умерь, коль сам не в состоянии работать с документацией и исх.текстами !
теперь по сабжу ...
если ты русский язык не понимаешь, то я ничем помочь тебе не смогу
цитирую себя:
Digitman © (20.05.04 12:30) [1]
последней строкойв обработчик OnError добавь
Socket.Close;
ты ВЫПОЛНИЛ эту рекомендацию ? Нет, не выполнил !!!!!
Какого же ... ты "почемукаешь" сейчас, а ?!
GroZ (2004-05-21 16:24:00) [5]И почему это должно работать, а то нет?
Digitman (2004-05-21 16:14:00) [6]procedure TIUS.ClientSocketError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
var
i : integer;
begin
i := TClientSocket(Sender).Tag;
with PrmConns[i] do
case ErrorEvent of
eeConnect : begin
Socket.Close;
Connecting := False;
CurrPort := CurrPort + 1;
if (CurrPort < Port.s) or (CurrPort > Port.e) then CurrPort := Port.s;
LastErrorTick := GetTickCount;
end;
end;
ErrorCode := 0;
end;
GroZ (2004-05-21 15:42:00) [7]никакой ощутимой утечки ресурсов в TaskManager'е не видно ..
GroZ (2004-05-21 15:36:00) [8]
procedure TIUS.ClientSocketError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
var
i : integer;
begin
i := TClientSocket(Sender).Tag;
case ErrorEvent of
eeConnect : begin
PrmConns[i].ClientSocket.Socket.Close;
CloseCnt := CloseCnt + 1;
PrmConns[i].CurrPort := PrmConns[i].CurrPort + 1;
if (PrmConns[i].CurrPort < PrmConns[i].Port.s) or (PrmConns[i].CurrPort > PrmConns[i].Port.e) then PrmConns[i].CurrPort := PrmConns[i].Port.s;
ErrorCode := 0;
PrmConns[i].LastErrorTick := GetTickCount;
PrmConns[i].Connecting := False;
end;
eeDisconnect : begin
Socket.Close;
CloseCnt := CloseCnt + 1;
ErrorCode := 0;
end;
end;
end;
В теге слиент-сокетов прописываются их индексы в дин. массиве ...
Digitman (2004-05-21 15:07:00) [9]если у тебя происходит ощутимая утечка ресурсов, это и так видно в окне TaskManager'а, и не зачем для этого часами ждать непонятно что
Digitman (2004-05-21 14:56:00) [10]
> Также в обработчике ошибки клиент-сокета (ClientSocket.OnError):
>
> PrmConns[i].Connecting := False;
каким образом у тебя обработчик "узнает" о значении i, т.е. индексе элемента массива, с которым ассоциировано гнездо, возбудившее в данный момент событие OnError() ?
GroZ (2004-05-21 14:53:00) [11]ок, запустил прогу опять ... подожду ещё пару часов и скажу код ошибки ...
Digitman (2004-05-21 14:46:00) [12]
> просто не может присоедениться к серверу
ОЕ всегда достаточно конкретную диагностику отказа выдает, с кодом ошибки - о ней и спрашиваю
> точно ли TClientSocket.Close закрывает сокет?
точно.
исходники компонента перед тобой, можешь сам убедиться
GroZ (2004-05-21 14:36:00) [13]просто не может присоедениться к серверу .. как если кабель локальной сети вырвать ....
А точно ли TClientSocket.Close закрывает сокет? .. может нужно TClientSocket.Socket.Close ????????
Digitman (2004-05-21 14:29:00) [14]
> не работает Outlook Express (не может приконнектится к серверу)
и что говорит конкретно ?
GroZ (2004-05-21 14:19:00) [15]Digitman,
проверил ... ничего не изменилось ... подсчитал OpenCnt и CloseCnt ... равны (максимум разница 2 как и следовало ожидать)
.
.
:(((((
Digitman (2004-05-21 13:16:00) [16]а для взведения флага Connecting существует событие OnConnecting
Digitman (2004-05-21 13:12:00) [17]проведи ТОЧНЫЙ подсчет : суммируй кол-во выполненных Open() (где угодно) и сопоставь ему кол-во выполненных ClientSocket.Active := False (где угодно вне обработчика OnError) и Socket.Close (в обработчике OnError)
GroZ (2004-05-21 13:05:00) [18]Digitman,
в OnError как раз и скидывется флаг Connecting .. а вот OnConnect ...
Сделал всё как ты говориш ... подожду несколько часов ... посмотрим ..
GroZ (2004-05-21 12:53:00) [19]2 Verg,
На самом деле уже проверил и Scoket.Close вместо ClientSocket.Active := false но к сожелению теже проблемы :(
Digitman (2004-05-21 12:52:00) [20]
> и если клиент не присоединён к серверу
ну и что ? ну не успел еще внутренний механизм коннекта отработать за эти 800 мс ! при том что сервер, предположим, заведомо активен, но сет.маршрут к нему достаточно сложен, время доставки запроса на коннект + время доставки подтверждения коннекта может занять и секунды и десятки секунд .. ты же , не дождавшись ни события OnConnect (как факт успешного коннекта) ни события OnError() (как факт, например, недоступности/неактивности сервера) тут же делаешь Close() гнезда и пытаешься вновь запустить коннект ..
if not PrmConns[i].ClientSocket.Active and not PrmConns[i].Connecting then begin
PrmConns[i].ClientSocket.Close;
вот здесь какой смысл закрывать гнездо, если оно и так не активно и не находится в состоянии установления соединения ? Просто сразу делай Open() !
if PrmConns[i].ClientSocket.Active and PrmConns[i].Connecting then begin
PrmConns[i].Connecting := False;
end;
а вот это вообще не нужно здесь - следует просто обработать события OnConnect или OnError, в которых и д.б. сброшен флаг Connecting