Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

странная проблема с сокетами: [D1, D2, D3, D4, D5, D6, D7, Win95/98, WinME, NT4, Win2k, WinXP]


Страницы:   1 2

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


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо