it-swarm.com.de

Schnellster Weg zum Testen der Internetverbindung

C # 2008 SP1

Ich verwende diesen Code, um eine Verbindung zu unserer Client-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 möchte also die httpWebRequest-Klasse verwenden, um eine Verbindung zu unserer Kunden-Website herzustellen. Wenn die Antwort in Ordnung ist, kann die Internetverbindung fortgesetzt werden. 

Mir ist jedoch aufgefallen, dass die Antwort zu lange dauert. Ich bin nicht sicher, ob dies ein sehr effizienter Test ist. 

Wenn ich jedoch zu ihrer Website browse, dauert das Laden der Seite weniger als eine Sekunde. Es dauert jedoch zu lange, wenn ich die HttpWebRequest-Klasse verwende

Voraussetzungen dafür sind:

Manchmal wird im Büro des Kunden ein Proxy verwendet. To Ich kann die TCPClient-Klasse nicht verwenden (hat keine Proxy-Eigenschaft).

Der Proxy unterstützt keine SOCKS, daher kann die Sockets-Klasse nicht verwendet werden.

Ich muss eine Timeout-Eigenschaft verwenden. Die WebClient-Klasse kann daher nicht verwendet werden. Dies liegt daran, dass das Softphone einfrieren würde, bis eine Antwort zurückgegeben wird. Also Timeout nach ein paar Sekunden.

Daher kann ich nur an die Klasse HttpWebRequest denken.

  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);
22
ant2009

Verwenden Sie P/Invoke, um InternetGetConnectedState aufzurufen. Das sollte Ihnen sagen, ob Sie eine Verbindung konfiguriert haben oder nicht. Sie können dann versuchen, die spezifische Verbindung zu Ihrem Dienst mithilfe von InternetCheckConnection zu überprüfen. Dies ist (manchmal) schneller als das direkte Anschließen der Verbindung, aber ich würde es testen, um zu sehen, ob es besser ist, als nur eine vollständige Verbindung von vornherein durchzuführen.

16
Reed Copsey

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

Ist die Netzwerkverbindung definitiv hergestellt, bevor Sie die Anfrage stellen können? Sind Sie auf jeden Fall nicht vorher Anfragen? Ich frage, weil ich feststelle, dass Sie die Antwort nicht zur Verfügung haben - wenn dies auch an anderer Stelle geschieht, stellen Sie möglicherweise fest, dass Sie mit dem Verbindungspool konfrontiert werden und Ihnen nur ein paar Verbindungen zu einem bestimmten Server geben. Die Moral ist, immer HttpWebResponses in eine using-Anweisung zu setzen. Natürlich kann das in Ihrem Fall nicht sein, aber es ist einen Versuch wert.

Wenn Ihre eigentliche Anwendung eine Verbindung zu einem anderen Ort herstellen wird, sollte dies auch der Test überprüfen. Machen Sie es im Grunde so nah wie möglich an das Reale.

Aus Interesse sagen Sie, dass es sich um eine "Softphone" -Anwendung handelt - läuft das tatsächlich on ein Telefon mit einer Beschreibung, das kompakte Framework verwendet, oder ist es eine Desktop-App?

11
Jon Skeet

Ich hatte eine ähnliche Situation, in der wir einen WCF-Anruf an einen Client tätigen würden, und es würde zu lange dauern, wenn der Client nicht erreichbar war (aus welchem ​​Grund auch immer). Was ich getan habe, war ein reines TCP-Socket für die Client-Adresse ... Dies schlägt fehl, wenn der Client den Port (in Ihrem Fall Port 80) nicht überwacht, und er ist schnell erfolgreich, wenn er vorhanden ist.

Dies gab mir die schnellste und genaueste Antwort, um festzustellen, ob ich mit dem Endpunkt kommunizieren kann, den ich erreichen wollte. Der einzige Nachteil ist, dass Sie das Timeout selbst auf dem Socket selbst verwalten müssen, da es nur Optionen für das Senden und das Empfangen von Timeouts gibt, keine Verbindung. 

Es geht so etwas ...

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 nicht den eigentlichen Code vor mir, aber das sollte Sie auf den allgemeinen Weg bringen.

6
Brian ONeil

Sie können auf den Microsoft.VisualBasic.Devices-Namespace verweisen, um den NetworkAvailableEventHandler-Delegaten und die Network-Klasse zu verwenden. Ich verwende die Network.IsAvailable-Eigenschaft und das Network.NetworkAvailableChanged-Ereignis, um zu überprüfen, ob das Netzwerk vorhanden ist (oder später betroffen ist), und dann ein HTTP-GET für meinen Server durchzuführen, um festzustellen, ob der Server vorhanden ist.

Dies hilft, das Problem etwas genauer zu melden, anstatt "Netzwerk nicht sehen" zu können.

2
Richard Watson

Eine bessere Option ist das Hinzufügen eines Verweises auf das Microsoft.VisualBasic und das Hinzufügen einer using-Anweisung Microsoft.VisualBasic.Device. Anschließend können Sie die folgende Codezeile verwenden, um die Verbindung zu einem beliebigen Netzwerk zu überprüfen.

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

request.GetResponse() sich selbst gibt eine Ausnahme aus, wenn der Hostname nicht aufgelöst werden kann. Daher möchten Sie vielleicht einen Try-Catch setzen, System.Net.WebException abfangen und den Fehlerstatus in der Status-Eigenschaft überprüfen. Ich bin mir nicht sicher, welcher Status genau kein Internet bedeuten würde. Die meisten Antworten könnten ebenso auf DNS oder andere Verbindungsprobleme zurückzuführen sein.

0
Nyerguds