22 Stimmen

Der schnellste Weg, die Internetverbindung zu testen

C# 2008 SP1

Ich verwende diesen Code, um eine Verbindung zu unserer Kunden-Website herzustellen. Dies ist für eine Softphone-Anwendung. Bevor der Benutzer einen Anruf tätigt, muss das Softphone prüfen, ob eine aktive Internetverbindung besteht.

Ich habe also die httpWebRequest-Klasse verwendet, um eine Verbindung zur Website unserer Kunden herzustellen. Wenn die Antwort in Ordnung ist, kann die Internetverbindung hergestellt werden.

Allerdings habe ich festgestellt, dass die Antwort zu lange auf sich warten lässt. Ich bin mir nicht sicher, ob dies nicht ein sehr effizienter Weg zum Testen ist.

Wenn ich jedoch ihre Website aufrufe, dauert es weniger als eine Sekunde, bis die Seite geladen ist. Aber es dauert zu lange, wenn ich die Klasse HttpWebRequest verwende

Die Voraussetzungen dafür sind also:

In manchen Fällen wird ein Bevollmächtigter im Büro des Kunden eingesetzt. Dazu kann ich die TCPClient-Klasse nicht verwenden (hat keine Proxy-Eigenschaft).

Der Proxy unterstützt SOCKS nicht und kann daher die Klasse Sockets nicht verwenden.

Ich muss eine Timeout-Eigenschaft verwenden. Daher kann ich die WebClient-Klasse nicht verwenden. Der Grund dafür ist, dass das Softphone einfrieren würde, bis eine Antwort zurückgegeben wird. Also Timeout nach ein paar Sekunden.

Also die einzige, die mir einfällt, ist die Klasse HttpWebRequest.

  HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.xxxxxxxxx.com");
            request.Timeout = 5000;
            request.Credentials = CredentialCache.DefaultNetworkCredentials;
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            if (response.StatusCode == HttpStatusCode.OK)
            {
                Console.WriteLine("IsSIPServerAvailable: " + response.StatusCode);
                isAvailable = true;
            }

\======== Bearbeiten mit p \Invoke ====

 [DllImport("wininet.dll", CharSet = CharSet.Auto)]
    private extern static bool InternetGetConnectedState(ref InternetConnectionState_e lpdwFlags, int dwReserved);

 [Flags]
    enum InternetConnectionState_e : int
    {
        INTERNET_CONNECTION_MODEM = 0x1,
        INTERNET_CONNECTION_LAN = 0x2,
        INTERNET_CONNECTION_PROXY = 0x4,
        INTERNET_RAS_INSTALLED = 0x10,
        INTERNET_CONNECTION_OFFLINE = 0x20,
        INTERNET_CONNECTION_CONFIGURED = 0x40
    }

 // In function for checking internet
 InternetConnectionState_e flags = 0;          
 bool isConnected = InternetGetConnectedState(ref flags, 0);

16voto

Reed Copsey Punkte 536986

Versuchen Sie P/Invoke zu verwenden, um InternetGetConnectedState . Das sollte Ihnen zeigen, ob Sie eine Verbindung konfiguriert haben oder nicht. Sie können dann versuchen, die spezifische Verbindung zu Ihrem Dienst zu überprüfen, indem Sie InternetCheckVerbindung . Dies ist (manchmal) schneller als eine direkte Verbindung, aber ich würde es testen, um zu sehen, ob es besser ist als eine vollständige Verbindung im Voraus.

3 Stimmen

Der Nachteil dabei ist (IMO), dass es nur angibt, ob der Computer mit dem "Internet im Allgemeinen" verbunden ist. Es ist nur ein gewisser Hinweis darauf, ob Sie in der Lage sein werden, den von Ihnen gewünschten Dienst zu nutzen. Der beste Weg, das herauszufinden, ist IMO, eine Verbindung zu genau diesem Dienst herzustellen. Natürlich ist das keine Garantie dafür, dass der Dienst auch eine Sekunde später noch gültig ist, aber ich denke, es ist ein besserer Indikator, wenn es möglich ist. (In manchen Fällen ist das nicht der Fall, z. B. wenn für das Herstellen der Verbindung eine Gebühr anfällt).

1 Stimmen

Ich habe meinen Code für den p/Invoke bearbeitet. Er sagt mir jedoch, ob das LAN mit meinem Computer verbunden ist (eingesteckt oder nicht). Er kann mir jedoch nicht sagen, ob ich eine aktive Internetverbindung habe (im Internet surfen).

0 Stimmen

@robUK: Ich habe meine Antwort bearbeitet, um den Aufruf von InternetCheckConnection aufzunehmen. Das ist ein weiteres P/Invoke, das Sie ausprobieren können - es sollte Ihnen sagen, ob diese spezifische URL verfügbar ist, aber ich glaube, es ist etwas schneller als der Versuch, selbst eine Verbindung herzustellen.

11voto

Jon Skeet Punkte 1325502

Was wird das Softphone für seine eigentliche Kommunikation verwenden? Geht das über HTTP/HTTPS an dieselbe Website? Wenn ja, ist das genau der richtige Weg - der nächste Schritt ist herauszufinden, warum es so lange dauert.

Besteht die Netzwerkverbindung definitiv, bevor Sie die Anfrage starten? Sind Sie definitiv no irgendwelche Anträge im Voraus stellen? Ich frage, weil mir aufgefallen ist, dass Sie die Antwort nicht entsorgen. Wenn das auch an anderer Stelle passiert, kann es sein, dass der Verbindungspool Ihnen nur ein paar Verbindungen zu einem bestimmten Server ermöglicht. Die Moral ist, dass immer setzen. HttpWebResponse s in einer using Erklärung. Natürlich kann das durchaus no das Problem in Ihrem Fall sein, aber es ist einen Versuch wert.

Wenn Ihre eigentliche Anwendung an anderer Stelle eine Verbindung herstellt, dann sollte Ihr Test auch dort ansetzen. Grundsätzlich sollten Sie den Test so realitätsnah wie möglich gestalten.

Aus Interesse sagen Sie, dass es sich um eine "Softphone"-Anwendung handelt - wird diese tatsächlich ausgeführt? auf ein Telefon, das das kompakte Framework verwendet, oder ist es eine Desktop-Anwendung?

0 Stimmen

Hallo. Es ist ein Desktop, der auf 2000, XP und Vista laufen kann. Das für die Info über die using-Anweisung. Das hatte ich vergessen. Der SIP-Server befindet sich auf demselben Server. Ich kann jedoch eine Verbindung über das SIP-Protokoll herstellen und über RTP streamen.

0 Stimmen

Wenn Sie später tatsächlich eine SIP-Verbindung herstellen wollen, warum dann nicht auch für den Test eine SIP-Verbindung herstellen? Gibt es eine SIP-Anfrage, die Sie nicht stellen müssen?

0 Stimmen

Ich untersuche gerade einige SIP-Anfragen. Ich mag auch die Option P/invoke unten. Ich denke, ich werde beide Optionen ausprobieren. danke.

6voto

Brian ONeil Punkte 4229

Ich hatte eine ähnliche Situation, in der wir einen WCF-Aufruf an einen Client tätigen wollten und es zu lange dauern würde, wenn der Client nicht erreichbar wäre (aus welchem Grund auch immer). Ich öffnete einen rohen TCP-Socket an die Client-Adresse... Dies schlägt schnell fehl, wenn der Client den Port nicht abhört (in Ihrem Fall Port 80), und ist schnell erfolgreich, wenn er dort ist.

So konnte ich am schnellsten und genauesten feststellen, ob ich in der Lage sein würde, mit dem gewünschten Endpunkt zu kommunizieren. Der einzige Nachteil ist, dass Sie die Zeitüberschreitung am Socket selbst verwalten müssen, da es nur Optionen für Sende- und Empfangszeitüberschreitung und nicht für die Verbindung gibt.

Es geht ungefähr so...

Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    try
    {
         IAsyncResult result = socket.BeginConnect("www.xxxxxxxxx.com", 80, null, null );
         //I set it for 3 sec timeout, but if you are on an internal LAN you can probably 
         //drop that down a little because this should be instant if it is going to work
         bool success = result.AsyncWaitHandle.WaitOne( 3000, true );

         if ( !success )
         {
                throw new ApplicationException("Failed to connect server.");
         }

         // Success
         //... 
    }
    finally
    {
         //You should always close the socket!
         socket.Close();
    }

Ich habe den Code, den ich verwendet habe, nicht vor mir, aber das sollte Sie auf den allgemeinen Weg bringen.

0 Stimmen

Hallo, danke für den Code. Eigentlich habe ich die Sockets-Klasse schon ausprobiert. Allerdings unterstützt der Proxy-Server, über den ich mich verbinden muss, das SOCKS-Protokoll nicht. Wenn der Proxyserver nicht wäre, wäre dies eine großartige Lösung.

0 Stimmen

ONiel, vielen Dank für diese Information. Ich war mit einem TcpClient, und es war viel viel langsamer als diese Methode.

0 Stimmen

Vielen Dank von diesem Googler! Ich habe versucht, herauszufinden, ob Port 25 (Mailserver-Port) vom Provider blockiert wurde, damit ich Port 2525 verwenden kann. Ihr Code verkürzte diesen Prozess von 30 Sekunden Wartezeit auf 3 Sekunden Wartezeit :)

2voto

Richard Watson Punkte 2544

Sie können den Microsoft.VisualBasic.Devices-Namensraum referenzieren, um den Delegaten NetworkAvailableEventHandler und die Klasse Network zu verwenden. Ich verwende die Network.IsAvailable-Eigenschaft und das Network.NetworkAvailabilityChanged-Ereignis, um zu prüfen, ob das Netzwerk vorhanden ist (oder später betroffen ist), und führe dann einen HTTP-GET an meinen Server aus, um zu sehen, ob der Server vorhanden ist.

Dies hilft dabei, das Problem etwas genauer zu beschreiben, anstatt nur "kann das Netzwerk nicht sehen".

1voto

Enyo Ginger Punkte 11

Eine bessere Option ist es, einen Verweis auf Microsoft.VisualBasic hinzuzufügen und eine using-Anweisung Microsoft.VisualBasic.Device hinzuzufügen, dann können Sie die folgende Codezeile verwenden, um zu prüfen, ob überhaupt eine Verbindung zu einem Netzwerk besteht.

public static bool isConnectedToNetwork {
   get {
      Network network = new Network();
      return network.IsAvailable;
   }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X