Socket error 10055

0

Mam pytanie. Napisałem aplikację gdzie dynamicznie tworzę w jednej strukturze obiekty TClientSocket, TTimer i TIdIcmp. Program działa następująco:
uruchamiam socket -> uruchamiam timer (interval = 1000) w OnTimer ustawiam TIdIcmp.Ping w OnReply steruje czy połączenie z socketem dalej jest czy już go nie ma (innej metody nie było). Ta dość zawiła konfiguracja o dziwo całkiem nieźle sobie radzi. Problem pojawia się gdy moją dynamiczną strukturę rozszerzam do np 200 (200 Socketow, Timerow i Pingow). Po pewnym czasie z windowsa leci mi komunikat Brak miejsca w buffowrze (API connect - 10055). Co prawda moja sieć oparta jest o kiepskiej jakości router dodatkowo całość leci po WiFi więc przypuszczam, że to może być problemem. Pytanie czy idzie jakoś z poziomu aplikacji lub systemu rozszerzyć ten buffor?

0

może napisz co to ma robić bo z tego opisu wynika, że próbujesz się podetrzeć papierem ściernym przetykanym drutem kolczastym

0

No to ok pełny opis:

Jest sobie struktura:

 type
  TDevs = record
    idx_device: Integer;
    nazwa: string;
    ip: string;
    port: Integer;  //port TCP
    haslo: integer;
    connected: Boolean;
    Conn: TClientSocket;
    id_os:string;
    id_event:string;
    tim: TTimer;
    idPing: TIdIcmpClient;
  end;

devs: array of TDevs;

Następnie w zależności od ilości urządzeń w bazie danych rozmiar tablicy devs się zmienia dla jednego urządzenia działa bez zarzutu dla 200 wywala komunikat (10055).

Gdy struktura jest już stworzona robię:

devs[i].conn.Active := true;

i czekam na zdarzenia z urządzeń. Ot cała filozofia. Problem pojawia się w momencie gdy np urządzenie ktoś wypnie z sieci, prądu lub z jakichś przyczyn się zawiesi. Niestety w takich wypadkach TClientSocket nie daje mi informacji czy połączenie z urządzeniem dalej jest aktywne więc dla każdego socketa z dynamicznej tabeli przypisany jest timer i co 1 sek timer puszcza pinga na ten sam adres. Gdy ping otrzyma odpowiedź (lub osiągnie timeout) ustawiam status:

 
procedure TfmMain.idPingReply(ASender: TComponent;
  const AReplyStatus: TReplyStatus);
begin
  if AReplyStatus.BytesReceived = 0 then
  begin
    if devs[(ASender as TIdIcmpClient).Tag].Conn.Active then
    begin
      devs[(ASender as TIdIcmpClient).Tag].Conn.Close;
      devs[(ASender as TIdIcmpClient).Tag].Connected := False;
    end
    else
      if devs[(ASender as TIdIcmpClient).Tag].Connected then
        UstawStatus(devs[(ASender as TIdIcmpClient).Tag].idx_device,false);
  end
  else
  begin
    if not devs[(ASender as TIdIcmpClient).Tag].Conn.Active then
    begin
      devs[(ASender as TIdIcmpClient).Tag].Conn.Open;
      devs[(ASender as TIdIcmpClient).Tag].Connected := True;
    end
    else
      if not devs[(ASender as TIdIcmpClient).Tag].Connected then
        UstawStatus(devs[(ASender as TIdIcmpClient).Tag].idx_device,True);
  end;
end;

Tak jak mówiłem problem pojawia się dla dużej ilości urządzeń gdyż sieć (lub API Windowsa XP) nie wyrabia.

0

Tak jak mówiłem problem pojawia się dla dużej ilości urządzeń gdyż sieć (lub API Windowsa XP) nie wyrabia.

1.Zrób to bez 199 Timerów (1 wystarczy)
2.Nie wysyłaj tego co 1 sec. dobrą wartością jest 10 sec jeżeli nie ma komunikacji, chociaż wszystko zależy od częstości użycia protokołu, np. w IRC timeout to 240sec. (ping leci co 120).

0

Te 199 timerów jest przygotowywane pod wielowątkowość dlatego taka dziwna konstrukcja. Finalnym założeniem będzie 1 urządzenie = 1 wątek :). Jedna sekunda natomiast jest podyktowana tym, że urządzenia operują z pieniędzmi dlatego w przypadku włamania do kasetki / lub wypięcia urządzenia z prądu (ludzie różnie kombinują) musi być niemal natychmiastowa reakcja.

0

Te 199 timerów jest przygotowywane pod wielowątkowość dlatego taka dziwna konstrukcja. Finalnym założeniem będzie 1 urządzenie = 1 wątek .

No to zamiast przyśpieszyć spowolni wszystko, no chyba że masz procesor który obsługuje naraz ~25 wątków.

Jedna sekunda natomiast jest podyktowana tym, że urządzenia operują z pieniędzmi dlatego w przypadku włamania do kasetki / lub wypięcia urządzenia z prądu (ludzie różnie kombinują) musi być niemal natychmiastowa reakcja.

No to zaopatrz się w pare komputerów. Jest ograniczona prędkość magistrali itd., jak będziesz sobie nawzajem z urządzeniami floodować to wszystko prędzej czy później padnie. Skoro wywala ci błędy to znaczy że przekroczyłeś już próg zapchania a osiągnełeś chaos.

A co do twojego oryginalnego pytania: czy ty wiesz jaki to 'bufor' ci się wywala że chcesz go zwiększyć?

0

To jakie inne rozwiązanie proponujecie jeśli nie pingowanie? Zadam pytanie zatem inaczej jak sprawdzić czy urządzenie wciąż jest podłączone?

0

Zadam pytanie zatem inaczej jak sprawdzić czy urządzenie wciąż jest podłączone?

Pingowanie, lub powiedzenie urządzeniowi żeby wysyłało ciągle jakiś pakiet.
Tylko twój problem polega na tym, że chcesz to robić tak szybko, jakbyś miał rakietę a nie komputer. pinguj wolniej/mniej urządzeń + w mniejszej ilości wątków (najlepiej mieć tyle wątków co procesor ew. *2 lub *4 - więcej to już bezwzględne tracenie na synchronizację, przełączanie itd.)
Albo zainteresuj się rozwiązaniem typowo hardwarowym (tutaj nie mogę niestety pomóc).

Jeszcze mam takiego pomysła: Skoro dzieje się to w LANie, to średnia prędkość będzie wysoka, więc zrób sobie tak ( w wielu wątkach, tylko bez przesady, to się nie ma zapychać):
1.Sprawdzasz jakie urządzenie nie było ostatnio sprawdzane
2.Wysyłasz ping
3.Odbierasz odpowiedź (zakładamy że potrwa to krótko)
4.Jeżeli nie otrzymasz po chwili to alarm
5.Skocz do pkt 1

Dzięki temu raczej będzie ci trudno zapchać sieć, ale jeżeli będzie to wolne (np. jakieś słabe Wifi) to czas może się okazać dłuższy niż przy klasycznym podejściu...

0

zamiast pingować wyślij cokolwiek - jak nie ma połączenie to dostaniesz błąd (TCP to gwarantuje) a jak jest podłączone to nawet nie musi tego w żaden sposób interpretować. Co do wątków i pingowania to to co napisał niesynaptyczny nie jest prawdą - sam ping, jeśli dany adres nie istnieje, trwa na tyle długo, że pingowanie nawet 20 adresów na raz ma sens

0

Co do wątków i pingowania to to co napisał niesynaptyczny nie jest prawdą - sam ping, jeśli dany adres nie istnieje, trwa na tyle długo, że pingowanie nawet 20 adresów na raz ma sens

Nie zabardzo rozumiem o co Tobie chodzi. Przecież zakładamy że adres istnieje przez 99.9% czasu, więc co z tego że to chwilę trwa (dajemy timeout na 1sec) - więc chyba źle rozumiem co napisałeś. Mógłbyś sprostować o co chodzi?

1 użytkowników online, w tym zalogowanych: 0, gości: 1