Jak stwierdzić mając IOException czy socket został zamknięty

0

Krótka historia sprawy: Łączę się z urządzeniami po Modbusie - w tym przypadku po TCP. Posiadam kod obecnie mniej więcej taki:

if (modbusMaster == null)
   modbusMaster = Create(); //nowe połączenie TCP
try
{
    modbusMaster.Read();
}
catch(Exception e)
{
    modbusMaster.Dispose(); //dispose połączenia
    modbusMaster = null;
}

Chciałbym ograniczyć disposowanie połączenia tylko wtedy gdy jest to absolutnie konieczne, to znaczy wtedy gdy faktycznie socket został zamknięty.

Normalnym jest, że czasem dostaję wyjątek System.IO.IOException: Nie można odczytać danych z połączenia transportowego: Próba połączenia nie powiodła się, ponieważ połączona strona nie odpowiedziała poprawnie po ustalonym okresie czasu... i wtedy wiem, że mogę działać na nim dalej.

Pytanie: Czy jest sposób, żeby rozpoznać po samym wyjątku czy połączenie zostało zamknięte. Chodzi konkretnie o IOException, bo co do SocketException i InvalidOperationException nie mam wątpliwości.

Dobrałem się do HRESULT poprzez int errorCode = Marshal.GetHRForException(e);. Dostałem wartość -2146232800 czyli 0x80131620, ale jak dotąd nie udało mi się tego rozkodować.

EDIT:
Znalazłem tutaj http://blogs.msdn.com/b/eldar/archive/2007/04/03/a-lot-of-hresult-codes.aspx
COR_E_IO 0x80131620 -2146232800
hmm ale to mi jakoś nie pomogło...
EDIT2:
Patrząc w źródła IOException ustawia tą wartość jako domyślną - fajnie.

    [__DynamicallyInvokable]
    public IOException(string message)
      : base(message)
    {
      this.SetErrorCode(-2146232800);
    }
0

to jak często dostajesz exception przy pracy, że jest to taki problem? Mam kilka programów za sobą, które komunikują się ze sterownikami przez modbus tcp i nigdy nie miałem problemu z błędami komunikacji, chyba że ktoś faktycznie wyłączył sterownik albo wypiął kabel. BTW programy pisane w delphi

0

No właśnie mamy interfejs który łączy się z 12 urządzeniami, z czego aktualnie uruchomione są 3. Stoi to na jednym połączniu TCP i połączenie jest co chwilę disposowane i tworzone na nowo, a być nie musi.

0

yyyyy... A jak to jest zrealizowane od strony sprzętowej? Jak włączysz urządzenie x bez rozłączania i ponownego łączenia to przy próbie dostania się do tegoż urządzenia dostaniesz błąd czy się połączysz? Bo jak się połączysz to po co zamykać połączenie?

Chodzi mi o to, że brak odpowiedzi od konkretnego urządzenia nie oznacza zerwanego połączenia. A z drugiej strony jak nie miałem połączenia na poziomie tcp to dostawałem jakiś socket exception a jak nie było odpowiedzi to chyba timeout

0

Urządzenia są podłączone do konwertera RS232<-->TCP więc połączenie TCP mam, ale samo urządzenie może nie odpowiadać. W takiej sytuacji dostaję IOException z SocketException w Inner jak widać:

System.IO.IOException: Nie można odczytać danych z połączenia transportowego: Próba połączenia nie powiodła się, ponieważ połączona strona nie odpowiedziała poprawnie po ustalonym okresie czasu lub utworzone połączenie nie powiodło się, ponieważ połączony host nie odpowiedział. ---> System.Net.Sockets.SocketException: Próba połączenia nie powiodła się, ponieważ połączona strona nie odpowiedziała poprawnie po ustalonym okresie czasu lub utworzone połączenie nie powiodło się, ponieważ połączony host nie odpowiedział

Testowałem teraz, że jak nie robię dispose na połączeniu tylko cały czas próbuję na tym pytać i "włączę urządzenia" to interfejs spokojnie się komunikuje.

Jak włączysz urządzenie x bez rozłączania i ponownego łączenia to przy próbie dostania się do tegoż urządzenia dostaniesz błąd czy się połączysz? Bo jak się połączysz to po co zamykać połączenie?

No właśnie, bo mogę też dostać IOException w innym przypadku chyba, gdy połączenie całe się wywali. Wtedy muszę na nowo tworzyć obiekty. Tu jest ten problem, że próbuję jakoś dojść do tego czy mam to połączenie czy nie. Coraz bardziej utwierdzam się w przekonaniu, że się w ten sposób nie da.

0

znaczy możesz odpytać wszystkie naście i jak żadne nie odpowie to znaczy, że połączenie dead

0

To jest uniwersalny interfejs i mamy tutaj trochę abstrakcji, więc na dobrą sprawę nie wiem ile urządzeń jest na połączeniu na tym poziomie. Nie byłoby to takie łatwe. Sprawa raczej jest przegrana i zostawiam to. Reaguję na IOException, SocketException i InvalidOperationException i tyle.

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