TcpListener przestaje nasłuchiwać po zerwaniu połączenia z net'em

0

Witam.
Mam aplikację WPF napisaną pod frameworka 4.8, która m.in. nasłuchuje na zadanym porcie z wykorzystaniem kontrolki TcpListener.
Wszystko działa dobrze do momentu zerwania połączenia z siecią (na testach odłączałem kabel od kompa). Wtedy metoda Pending() zawsze zwraca wartość false, niezależnie czy kabel jest odłączony czy ponownie podłączony (nie wywala żadnego błędu).

Czy jest jakaś metoda aby sprawdzić czy metoda Pending() działa poprawnie (tzn. czy nasłuchiwanie jest nadal aktywne)?

Próbowałem już sprawdzać właściwości IsBound, Active itp. Socketa ale nie zmieniają one swojego stanu po rozłączeniu sieci.
Wprowadziłem sprawdzanie podłączenia do sieci metodą NetworkInterface.GetIsNetworkAvailable() i to działa prawidłowo. Ale takie sprawdzanie mam co 10 milisekund. Boję się krótkotrwałego zerwania połączenia, w które nie trafię.

Czy jest jakaś metoda aby sprawdzać stan samego TcpListener'a?

1

Generalnie nie da się tego tak zrobić, jedyną opcją jest próba wysłania/odebrania pakietu i na tej podstawie stwierdzenia czy połączenie jest aktywne. Tu cytat z dokumentacji (pogrubienie moje)

Because the Connected property only reflects the state of the connection as of the most recent operation, you should attempt to send or receive a message to determine the current state. After the message send fails, this property no longer returns true. Note that this behavior is by design. You cannot reliably test the state of the connection because, in the time between the test and a send/receive, the connection could have been lost. Your code should assume the socket is connected, and gracefully handle failed transmissions.

(link)

W tym cytacie najważniejsze jest ostatnie zdanie, że powinieneś założyć że połączenie jest aktywne i odpowiednio obsługiwać błedy.

0

Moment, co ma Pending() do odłączenia kabla?
Jak konstruktor ani Start() nie wywalą wyjątku to serwer stoi dopóki nie odpalisz Stop()
Odciąłeś kabel? To co z tego nadal serwer siedzi i może odpowiadać na localhost

0
markone_dev napisał(a):

Generalnie nie da się tego tak zrobić, jedyną opcją jest próba wysłania/odebrania pakietu i na tej podstawie stwierdzenia czy połączenie jest aktywne. Tu cytat z dokumentacji (pogrubienie moje)

Because the Connected property only reflects the state of the connection as of the most recent operation, you should attempt to send or receive a message to determine the current state. After the message send fails, this property no longer returns true. Note that this behavior is by design. You cannot reliably test the state of the connection because, in the time between the test and a send/receive, the connection could have been lost. Your code should assume the socket is connected, and gracefully handle failed transmissions.

(link)

W tym cytacie najważniejsze jest ostatnie zdanie, że powinieneś założyć że połączenie jest aktywne i odpowiednio obsługiwać błedy.

Mój kod z zaimplementowanym sprawdzaniem podłączenia do sieci:


                bool netConn = NetworkInterface.GetIsNetworkAvailable();

                while (true)
                {
                    try
                    {
                        System.Threading.Thread.Sleep(10);

                        if (!netConn)
                        {
                            if (NetworkInterface.GetIsNetworkAvailable())
                            {
                                err = true;
                                netConn = true;
                                serwer.Stop();
                            }
                        }
                        else
                            netConn = NetworkInterface.GetIsNetworkAvailable();

                        if (netConn && !err)
                        {
                            if (serwer.Pending())
                            {
                                System.Net.Sockets.TcpClient client = serwer.AcceptTcpClient();
                                RefreshConfigs();
                            }
                            err = false;
                        }
                    }
                    catch (Exception exp)
                    {
                        err = true;
                    }

                    if (err)
                    {
                        try
                        {
                            serwer = null;
                            serwer = new System.Net.Sockets.TcpListener(ip, port);
                            serwer.Start();
                            err = false;
                        }
                        catch (Exception exp)
                        {
                        }
                    }
                }
                
0
_13th_Dragon napisał(a):

Moment, co ma Pending() do odłączenia kabla?
Jak konstruktor ani Start() nie wywalą wyjątku to serwer stoi dopóki nie odpalisz Stop()
Odciąłeś kabel? To co z tego nadal serwer siedzi i może odpowiadać na localhost

No i w tym problem. Metoda Pending() po utracie podłączenia do sieci i ponownym jego odzyskaniu nie zwraca już przychodzących połączeń. Dlatego szukam rozwiązania tego problemu.

0
WojtexProgramista napisał(a):
_13th_Dragon napisał(a):

Moment, co ma Pending() do odłączenia kabla?
Jak konstruktor ani Start() nie wywalą wyjątku to serwer stoi dopóki nie odpalisz Stop()
Odciąłeś kabel? To co z tego nadal serwer siedzi i może odpowiadać na localhost

No i w tym problem. Metoda Pending() po utracie podłączenia do sieci i ponownym jego odzyskaniu nie zwraca już przychodzących połączeń. Dlatego szukam rozwiązania tego problemu.

A z localhost zwraca?

0

A więc tak.

NetworkInterface.GetIsNetworkAvailable sprawdza czy jakiekolwiek połączenie jest aktywne. Z dokumentacji:

Indicates whether any network connection is available.

link

Więc to nie zadziała w sytuacji jeżeli będziesz miał więcej niż 1 kartę sieciową aktywną, bo sprawdza czy jakiekolwiek połączenie jest dostępne.

Żeby uprościc kod możesz zasubskrybować się na zdarzenie NetworkAvailabilityChanged link. To zdarzenie pod spodem jest oparte o metodę NetworkInterface.GetIsNetworkAvailable więc zrobi to co ty teraz robisz tylko bez tego spaghetti bo wystarczy sobie napisać pod to zdarzenie handler NetworkAvailabilityChangedEventHandler link

Do sprawdzania stanu połączenia mógłbyś też użyć klasy TcpConnectionInformation . Z dokumentacji:

Provides information about the Transmission Control Protocol (TCP) connections on the local computer.

link

Klasa zwraca obiekt TcpConnectionInformation który zawiera property State która jest enumem TcpState i wartość enuma wskazuje na stan protokołu TCP

Specifies the states of a Transmission Control Protocol (TCP) connection.

link

Wartości enuma:

Closed 1
The TCP connection is closed.

CloseWait 8
The local endpoint of the TCP connection is waiting for a connection termination request from the local user.

Closing 9
The local endpoint of the TCP connection is waiting for an acknowledgement of the connection termination request sent previously.

DeleteTcb 12
The transmission control buffer (TCB) for the TCP connection is being deleted.

Established 5
The TCP handshake is complete. The connection has been established and data can be sent.

FinWait1 6
The local endpoint of the TCP connection is waiting for a connection termination request from the remote endpoint or for an acknowledgement of the connection termination request sent previously.

FinWait2 7
The local endpoint of the TCP connection is waiting for a connection termination request from the remote endpoint.

LastAck 10
The local endpoint of the TCP connection is waiting for the final acknowledgement of the connection termination request sent previously.

Listen 2
The local endpoint of the TCP connection is listening for a connection request from any remote endpoint.

SynReceived 4
The local endpoint of the TCP connection has sent and received a connection request and is waiting for an acknowledgment.

SynSent 3
The local endpoint of the TCP connection has sent the remote endpoint a segment header with the synchronize (SYN) control bit set and is waiting for a matching connection request.

TimeWait 11
The local endpoint of the TCP connection is waiting for enough time to pass to ensure that the remote endpoint received the acknowledgement of its connection termination request.

Unknown 0
The TCP connection state is unknown.

0

na jakim adresie startujesz nasłuch?

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