2009-06-15 16 views
7

मेरे पास WinForms ऐप है, और मैं फॉर्म पर प्रदर्शित आईपी की सूची के लिए रिवर्स DNS प्रविष्टियां प्राप्त करने का प्रयास कर रहा हूं।GetHostEntry बहुत धीमा है

मुख्य मुद्दा मैं आई है System.Net.Dns.GetHostEntry हास्यास्पद धीमी है, विशेष रूप से जब कोई रिवर्स DNS प्रविष्टि पाया जाता है। सीधे DNS के साथ, यह तेज़ होना चाहिए, क्योंकि DNS सर्वर NXDOMAIN वापस करेगा। आंतरिक रूप से, यह ws2_32.dll getnameinfo() पर कॉल कर रहा है, जिसमें कहा गया है "नाम समाधान डोमेन नाम सिस्टम (DNS), स्थानीय होस्ट फ़ाइल, या अन्य नामकरण तंत्र द्वारा किया जा सकता है" - इसलिए मुझे लगता है कि यह उन "अन्य नामकरण तंत्र" है जो इसे उत्पन्न कर रहा है इतनी धीमी हो, लेकिन क्या कोई जानता है कि ये तंत्र क्या हैं?

आम तौर पर यह, आईपी प्रति 5 सेकंड ले जा रहा है, जब तक यह एक रिवर्स प्रवेश पाता है, और फिर इसे लगभग तत्काल है। मैंने आंशिक रूप से धागे का उपयोग करके इस बारे में काम किया है, लेकिन चूंकि मैं एक बड़ी सूची कर रहा हूं और मैं केवल एक ही धागे को एक बार चला सकता हूं, फिर भी उन सभी को प्राप्त करने में कुछ समय लगता है।

क्या रिवर्स डीएनएस प्रविष्टियों को खोजने का एक बेहतर तरीका है जो तेजी से होने वाला है?

उत्तर

5

दुर्भाग्य से, वहाँ कोई रास्ता नहीं है (जिनमें से मैं वाकिफ हूँ) Windows API में इस समयबाह्य बदलने के लिए, क्लाइंट की तरफ है। सबसे अच्छा आप रजिस्ट्री को DNS क्वेरी में टाइमआउट की लंबाई को बदलने के लिए संपादित कर सकते हैं। विवरण के लिए this technet article देखें। मेरे ज्ञान के लिए, प्रयास करते समय 1, 2, & 3 चलाए जाते हैं, इसलिए 5 सेकंड देरी होती है।

केवल अन्य विकल्प ऐसे रिवर्स DNS खोज के इस asynchronous version के रूप में पृष्ठभूमि प्रसंस्करण के कुछ फार्म, उपयोग करने के लिए है। यह थ्रेडिंग का उपयोग करने जा रहा है, हालांकि, आप अंततः टाइमआउट में भाग लेंगे (यह बेहतर होगा, क्योंकि यह कई प्रतीक्षा धागे में होगा, लेकिन फिर भी सही नहीं है)। व्यक्तिगत रूप से, यदि आप एक बड़ी संख्या में संसाधित करने जा रहे हैं, तो मैं दोनों दृष्टिकोणों को मिश्रित करूंगा - एक रिवर्स लुकअप को अनन्य रूप से करें और टाइमआउट को कम करने के लिए रजिस्ट्री को संशोधित करें। टिप्पणी के बाद


संपादित करें:

आप getnameinfo पर झंडे को देखें, तो वहाँ एक झंडे पैरामीटर है। मुझे विश्वास है कि आप इसमें शामिल होने के लिए पी/इनवॉक कर सकते हैं और झंडे NI_NAMEREQD | NI_NUMERICHOST सेट कर सकते हैं। (पहला कोई त्रुटि नहीं है कि कोई DNS प्रविष्टि नहीं है, जो टाइमआउट में मदद करता है - दूसरा रिवर्स लुकअप करने के लिए कहता है।)

+1

मैंने वास्तव में उस संस्करण का उपयोग शुरू करने के लिए किया था। यह प्रभावी रूप से टाइमआउट समस्या के आसपास हो जाता है। मेरी समस्या यह है कि बिल्कुल एक टाइमआउट होना चाहिए। कुछ यादृच्छिक आईपी के साथ कमांड लाइन पर चलाएं या कमांड लाइन पर लॉग ऑन करें - यह आम तौर पर <1 एस में वापस आ जाएगा और कहें "*** server.pf.local 42.23.1.42 नहीं मिल सकता: अस्तित्वहीन डोमेन" (या NXDOMAIN, खुदाई के मामले में) - मुझे आश्चर्य है कि GetHostEntry() एक ही तरीके से क्यों काम नहीं करता है। – gregmac

+0

मेरा मानना ​​है कि आप getnameinfo पर डिफ़ॉल्ट की तुलना में विभिन्न झंडे का उपयोग करके पी/इनवॉक के माध्यम से जो चाहते हैं उसे पूरा कर सकते हैं। मेरा संपादन देखें। –

0

मुख्य रूप से किसी को Google के माध्यम से यह पता चलता है कि एक टिप्पणी जोड़कर, जैसा मैंने किया था। ..

व्यवहार ओएस संस्करण विशिष्ट हो सकता है; ये नोट्स सर्वर 2008 आर 2 के लिए लागू होते हैं।

NI_NUMERICHOST ध्वज वह नहीं करता जो आप चाहते हैं; इस मामले में मेजबान नाम के बजाए मेजबान पहचानकर्ता (यानी: आईपी पता) के संख्यात्मक संस्करण को वापस करने के लिए एपीआई।

भी NI_NAMEREQD साथ

, वहां अभी भी एक टाइमआउट है अगर जानकारी (डिफ़ॉल्ट रूप से 5 सेकंड) नहीं मिला है। मुझे यकीन नहीं है कि यह एक कैस्केडिंग लुकअप टाइमआउट, या कुछ और के कारण है, लेकिन यह ध्वज टाइमआउट को रोकता नहीं है (न ही कोई अन्य ध्वज, जहां तक ​​मैं कह सकता हूं)।

यह इस कॉल WSALookupService एपीआई, आंतरिक रूप से है, हालांकि यह स्पष्ट नहीं है कि क्या झंडे पारित कर दिया जा रहा है प्रकट होता है। साथ ही, ध्यान दें कि लौटाई गई जानकारी गलत हो सकती है; मेरे परीक्षण मामलों में से एक में, nslookup ने कोई परिणाम नहीं दिया, लेकिन getnameinfo गलत और अयोग्य नाम के रूप में लौटा। तो ... हाँ, अभी तक कोई अच्छा जवाब नहीं है, लेकिन उम्मीद है कि यह जानकारी उपयोगी है।

8

शायद यह मदद कर सकता है?dead link.

(Dead link: http://www.chapleau.info/blog/2008/09/09/reverse-dns-lookup-with-timeout-in-c.html)

कोड की WayBack मशीन संस्करण, भावी पीढ़ी के लिए:

private delegate IPHostEntry GetHostEntryHandler(string ip); 

public string GetReverseDNS(string ip, int timeout) 
{ 
    try 
    { 
     GetHostEntryHandler callback = new GetHostEntryHandler(Dns.GetHostEntry); 
     IAsyncResult result = callback.BeginInvoke(ip,null,null); 
     if (result.AsyncWaitHandle.WaitOne(timeout, false)) 
     { 
      return callback.EndInvoke(result).HostName; 
     } 
     else 
     { 
      return ip; 
     } 
    } 
    catch (Exception) 
    { 
     return ip; 
    } 
} 
+1

मृत लिंक ... :( –

4

आप काफी in-addr.arpa डोमेन पूछताछ की एक असफल देखने की गति में सुधार कर सकते हैं। E.g आईपी पते एबी.सी.डी के लिए एक रिवर्स आईपी लुकअप करने के लिए आपको डोमेन डी.सी.बी.ए.ए.-addr.arpa के लिए DNS से ​​पूछना चाहिए। यदि रिवर्स लुकअप संभव है तो होस्ट नाम के साथ एक पीटीआर रिकॉर्ड वापस कर दिया जाता है।

दुर्भाग्य से .NET के पास DNS पूछताछ के लिए एक सामान्य API नहीं है। लेकिन पी/Invoke का उपयोग करके आप वांछित परिणाम प्राप्त करने के लिए DNS API को कॉल कर सकते हैं (रिवर्स लुकअप विफल होने पर फ़ंक्शन null लौटाएगा)।

using System; 
using System.ComponentModel; 
using System.Linq; 
using System.Net; 
using System.Runtime.InteropServices; 

public static String ReverseIPLookup(IPAddress ipAddress) { 
    if (ipAddress.AddressFamily != AddressFamily.InterNetwork) 
    throw new ArgumentException("IP address is not IPv4.", "ipAddress"); 
    var domain = String.Join(
    ".", ipAddress.GetAddressBytes().Reverse().Select(b => b.ToString()) 
) + ".in-addr.arpa"; 
    return DnsGetPtrRecord(domain); 
} 

static String DnsGetPtrRecord(String domain) { 
    const Int16 DNS_TYPE_PTR = 0x000C; 
    const Int32 DNS_QUERY_STANDARD = 0x00000000; 
    const Int32 DNS_ERROR_RCODE_NAME_ERROR = 9003; 
    IntPtr queryResultSet = IntPtr.Zero; 
    try { 
    var dnsStatus = DnsQuery(
     domain, 
     DNS_TYPE_PTR, 
     DNS_QUERY_STANDARD, 
     IntPtr.Zero, 
     ref queryResultSet, 
     IntPtr.Zero 
    ); 
    if (dnsStatus == DNS_ERROR_RCODE_NAME_ERROR) 
     return null; 
    if (dnsStatus != 0) 
     throw new Win32Exception(dnsStatus); 
    DnsRecordPtr dnsRecordPtr; 
    for (var pointer = queryResultSet; pointer != IntPtr.Zero; pointer = dnsRecordPtr.pNext) { 
     dnsRecordPtr = (DnsRecordPtr) Marshal.PtrToStructure(pointer, typeof(DnsRecordPtr)); 
     if (dnsRecordPtr.wType == DNS_TYPE_PTR) 
     return Marshal.PtrToStringUni(dnsRecordPtr.pNameHost); 
    } 
    return null; 
    } 
    finally { 
    const Int32 DnsFreeRecordList = 1; 
    if (queryResultSet != IntPtr.Zero) 
     DnsRecordListFree(queryResultSet, DnsFreeRecordList); 
    } 
} 

[DllImport("Dnsapi.dll", EntryPoint = "DnsQuery_W", ExactSpelling=true, CharSet = CharSet.Unicode, SetLastError = true)] 
static extern Int32 DnsQuery(String lpstrName, Int16 wType, Int32 options, IntPtr pExtra, ref IntPtr ppQueryResultsSet, IntPtr pReserved); 

[DllImport("Dnsapi.dll", SetLastError = true)] 
static extern void DnsRecordListFree(IntPtr pRecordList, Int32 freeType); 

[StructLayout(LayoutKind.Sequential)] 
struct DnsRecordPtr { 
    public IntPtr pNext; 
    public String pName; 
    public Int16 wType; 
    public Int16 wDataLength; 
    public Int32 flags; 
    public Int32 dwTtl; 
    public Int32 dwReserved; 
    public IntPtr pNameHost; 
} 
+0

यह एक हल करने योग्य पते के लिए ठीक काम करता है, लेकिन जब मैंने इसे एक अनजान पता दिया तो लटका दिया। – JimSTAT

0

मामले में किसी को भी इस हिट ...

मैं बजाय अप्रचलित Dns.GetHostByName बुला लिए TcpClient निर्माता में स्विच।

किसी भी कारण से यह बहुत बेहतर प्रदर्शन करता है।

public TcpClientIP(string hostname, int port) : base() 
{ 
    try 
    { 
     if (_legacyDnsEnabled) 
     { 
      var host = Dns.GetHostByName(hostname); 
      var ips = host.AddressList.Select(o => new IPAddress(o.GetAddressBytes())).ToArray(); 
      Connect(ips, port); 
      return; 
     } 
    } 
    catch(SocketException e) 
    { } 

    Connect(hostname, port); 
} 
+0

यह केवल तभी काम करता है जब आपके पास पहले से होस्टनाम हो, न कि आपके पास आईपी पता है और एक होस्टनाम जैसा चाहता है मूल सवाल –

संबंधित मुद्दे