簡體   English   中英

SocketException:主機查找失敗:'...com'(操作系統錯誤:提供節點名或服務名,或未知,errno = 8)

[英]SocketException: Failed host lookup: ‘...com’ (OS Error: nodename nor servname provided, or not known, errno = 8)

我們處於生產應用程序面臨以下套接字異常並且在此之后無法執行任何其他網絡操作的情況。

DioError [DioErrorType.DEFAULT]: SocketException: Failed host lookup: ‘xyz.abc.com’ (OS Error: nodename nor servname provided, or not known, errno = 8)

注意:重復遇到一位擁有 iPhone X 的用戶,iOS 14.4

我們使用Dio作為網絡客戶端, Retrofit內部使用來自 dart 的 HttpClient。 對於 Dio,異常無法在模擬環境中重現,但直接使用 HttpClient,可以在 iOS 模擬器中使用以下代碼重現相同的異常。

HttpClient userAgent = new HttpClient();
  bool run = true;
  while (run) {
    try {
      await userAgent.getUrl(Uri.parse('https://www.google.com'));
      print('Number of api executed');
    } catch (e) {
      print(e);
      if (e is SocketException) {
        if ((e as SocketException).osError.errorCode == 8)
          print('***** Exception Caught *****');
      }
    }
  }

拋出異常后,HttpClient 無法從陳舊的 state 中恢復,所有其他 API 請求開始失敗並出現相同的錯誤。

在此處輸入圖像描述

通過強制關閉所有先前的連接並打開一個新的 HttpClient,我們能夠從陳舊的 state 中恢復。

  HttpClient userAgent = new HttpClient();
  bool run = true;
  while (run) {
    try {
      await userAgent.getUrl(Uri.parse('https://www.google.com'));
      print('Number of api executed');
    } catch (e) {
      print(e);

      if (e is SocketException) {
        if ((e as SocketException).osError.errorCode == 8)
          print('***** Exception Caught *****');
      }
      userAgent.close(force: true);
      print('Force closing previous connections');
      userAgent = HttpClient();
      print('Creating new HttpClient instance');
    }
  }

在此處輸入圖像描述

一個有趣的事實是在每 236 個請求之后引發異常。 這可能是因為文件描述符過度使用,但 iOS 的限制為 256。

有了穩定的互聯網連接,這個問題每次都可以在 iOS 模擬器中重現。

雖然我無法重現 Dio 客戶端的問題,但在生產中它正在發生。 因此,我正在尋求幫助以了解此問題的根本原因,以及我們如何預防它?

任何遇到過這種情況以及如何克服它的人,請幫助我。

提前致謝。

我用這段代碼解決了同樣的問題:-

示例

//Add This Class
    class MyHttpOverrides extends HttpOverrides{
      @override
      HttpClient createHttpClient(SecurityContext? context){
        return super.createHttpClient(context)
          ..badCertificateCallback = (X509Certificate cert, String host, int port)=> true;
      }
    }
    
    Future<void> main() async {
      HttpOverrides.global = MyHttpOverrides();      //call here
      runApp(const MyApp());
    }

這是一個奇怪的錯誤。

這可能無法回答您的問題,但可能會促使我們弄清楚發生了什么。

代碼片段(從問題中復制)將在每個.getUrl()調用中打開一個新的stream並且不會關閉它們 (我假設這是故意創建套接字異常?)

HttpClient userAgent = new HttpClient();
  bool run = true;
  while (run) {
    try {
      await userAgent.getUrl(Uri.parse('https://www.google.com'));
      print('Number of api executed');
    } catch (e) {
      print(e);
      if (e is SocketException) {
        if ((e as SocketException).osError.errorCode == 8)
          print('***** Exception Caught *****');
      }
    }
  }

在某些時候,達到了(開放流的)限制。 我想在你的情況下這個幻數是 236。

那么在這一點上,當您看到nodename or servname provided的異常時?

(順便說一句,我認為錯誤來自底層主機操作系統的 DNS 服務,盡管我不確定這是否是由於請求垃圾郵件、打開的連接數等。這可能不是相關信息.)

因此,如果您以典型的方式使用HttpClient ,發出請求並關閉那些打開的流,例如:

      var request = await userAgent.getUrl(Uri.parse('http://example.com/'));
      var response = await request.close(); // ← close the stream
      var body = await response.transform(utf8.decoder).join();
      // ↑ convert results to text
      // rinse, repeat... 

...您是否仍然看到相同的nodename or servname provided的錯誤彈出?

使用上面的“典型用法”代碼,可以重用userAgent ,直到調用userAgent.close() (並且 HttpClient 永久關閉。再次嘗試使用它會引發Bad State異常)。

我很想知道這個修改后的代碼是否仍然出現節點名錯誤。


回復:問題的第二個代碼片段。

在 catch 塊中, HttpClient被關閉,然后創建一個新的HttpClient 這有效地關閉了在try塊中打開的所有打開流(我假設,重置打開流的限制。)

如果您調整第二個代碼示例以使用:

      var req = await userAgent.getUrl(Uri.parse('https://www.google.com'));
      userAgent.close(force: true);
      userAgent = HttpClient();
      print('Number of api executed');

你能無限期地運行它嗎?

1:獲取文件描述符的當前限制

ulimit -n 示例 output:“256”或“10032”。

提示:在 MacOS 上,可以指定的最大數量為 12288。

獲取當前進程限制

ulimit -u 示例 output:“1418”。

sudo launchctl 限制 maxfiles 65536 200000

我在生產中遇到了完全相同的錯誤,它間歇性地發生。 就像貝克所說,關閉連接:

import 'package:http/http.dart' as http;

Future<http.Response> get(String url) async {
    var httpClient = http.Client() as http.BaseClient;
    
    Map<String, String> headers = {};
    headers['Content-Type'] = 'application/json; charset=UTF-8';

    var result = await httpClient
        .get(Uri.parse(url), headers: headers)
        .timeout(
            const Duration(seconds: 60),
            onTimeout: () => http.Response('Request Timeout', 408),
        );
    
    httpClient.close();
    
    return result;
}

我做了 10 Future.Delayeds ,每次循環執行 300 個get請求,但沒有發現任何問題。

未來的延遲是這樣完成的:

Future.delayed(const Duration(milliseconds: 10), () async {
  for (var i = 0; i < 300; i++) {
    var pingResult = await Api.instance.ping();
    print('Delayed 1 Result (${i}): ${pingResult.success}');
  }
});

Future.delayed(const Duration(milliseconds: 10), () async {
  for (var i = 0; i < 300; i++) {
    var pingResult = await Api.instance.ping();
    print('Delayed 2 Result (${i}): ${pingResult.success}');
  }
});

//..

我也發現了同樣的問題,試了各種方法都找不到原因。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

相關問題 SocketException(SocketException:主機查找失敗:'test'(操作系統錯誤:提供了節點名或服務名,或未知,errno = 8)) SocketException:主機查找失敗:&#39;..co&#39;(操作系統錯誤:提供節點名或服務名,或未知,errno = 8) iOS 上的 Flutter 應用程序拋出 SocketException:主機查找失敗:'google.com'(操作系統錯誤:提供了節點名或服務名,或未知,errno = 8) 如何解決 SocketException: Failed host lookup: &#39;www.xyz.com&#39; (OS Error: No address associated with hostname, errno = 7) SocketException:主機查找失敗:'methods.abc.com'(操作系統錯誤:沒有與主機名關聯的地址,errno = 7),StackTrace: 未處理的異常:SocketException:主機查找失敗:(操作系統錯誤:沒有與主機名關聯的地址,errno = 7) Flutter 當我從 api 獲取數據時顯示 SocketException:主機查找失敗:(操作系統錯誤:沒有與主機名關聯的地址,errno = 7) 如何解決失敗的主機查找:'firebasestorage.googleapis.com'(操作系統錯誤:沒有與主機名關聯的地址,errno = 7) Flutter-SocketException:連接失敗(操作系統錯誤:網絡無法訪問,errno = 101) Flutter SocketException:操作系統錯誤:沒有到主機的路由,errno = 113,地址 = xxxx,端口 = 42376
 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM