首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 實作 WHOIS 域名查詢:TCP 43 埠協議解析與多伺服器路由完整範例

     編輯:關於C語言

前言:WHOIS 協議簡介

WHOIS 協議(RFC 3912)基於 TCP 43 埠,客戶端連線伺服器發送域名字串(以 CRLF 結尾),伺服器回傳註冊資訊純文字。無加密、無驗證、無狀態。核心挑戰在於:**不同頂級域(TLD)對應不同 WHOIS 伺服器**,需建立路由表或遞迴查詢。

基礎查詢:直連 Network Solutions

// query_internic.aspx
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Net.Sockets" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.IO" %>

進階:多 TLD 智慧路由查詢

// query_registries.aspx
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Net.Sockets" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Collections" %>


Domain:

核心邏輯深度解析

1. 協議細節

  • 請求:域名 + \r\n(必須 CRLF)
  • 回應:純文字多行,以連線關閉結束
  • 編碼:傳統伺服器用 ASCII/ISO-8859-1,現代支援 UTF-8

2. TLD 路由策略

策略說明優/缺點
靜態對照表硬編碼常用 TLD 伺服器快、簡單,但需維護
IANA 根區查詢查詢 whois.iana.org 取得 referral權威、自動更新,但多一次 RTT
DNS SRV 記錄查詢 _whois._tcp.tld標準化,但部署率低
遞迴 Referral 追蹤解析回應中的 "refer:" 或 "whois:" 欄位通用,需解析非結構化文字

3. 進階解析:結構化資料提取

// 簡易欄位提取範例
var dict = new Dictionary();
foreach (var line in rawResponse.Split('\n'))
{
    var idx = line.IndexOf(':');
    if (idx > 0)
    {
        var key = line.Substring(0, idx).Trim().ToLower();
        var val = line.Substring(idx + 1).Trim();
        if (!dict.ContainsKey(key)) dict[key] = val;
    }
}
// 常見欄位:domain name, registrar, creation date, expiration date, name server, status

生產級增強建議

  1. 快取:WHOIS 資料變動較緩,建議快取 24 小時(MemoryCache/Redis)
  2. 非同步與逾時:TcpClient.ConnectAsync + CancellationToken 設定 10 秒逾時
  3. 速率限制:多數 WHOIS 伺服器限制查詢頻率,需實作 Token Bucket / 漏桶演算法
  4. 支援 IDN:國際化域名需先 IdnMapping.GetAscii 轉 Punycode 再查詢
  5. RDAP 替代:現代替代協議(HTTP/JSON/REST),支援結構化回應、認證、國際化,漸漸取代 WHOIS

完整主控台版本

using System;
using System.Net.Sockets;
using System.Text;
using System.Collections.Generic;

class WhoisClient
{
    static readonly Dictionary Servers = new()
    {
        ["com"] = "whois.verisign-grs.com",
        ["net"] = "whois.verisign-grs.com",
        ["org"] = "whois.pir.org",
        ["io"] = "whois.nic.io",
        ["ai"] = "whois.nic.ai",
        ["cn"] = "whois.cnnic.cn",
        ["tw"] = "whois.twnic.net.tw",
        ["jp"] = "whois.jprs.jp",
        ["kr"] = "whois.kr",
        ["de"] = "whois.denic.de",
        ["uk"] = "whois.nic.uk",
        ["fr"] = "whois.nic.fr",
        ["eu"] = "whois.eu",
        ["app"] = "whois.nic.google",
        ["dev"] = "whois.nic.google"
    };

    static void Main(string[] args)
    {
        if (args.Length == 0) { Console.WriteLine("Usage: WhoisClient domain.com"); return; }
        string domain = args[0].ToLower();
        string tld = domain.Split('.')[^1];
        string server = Servers.ContainsKey(tld) ? Servers[tld] : "whois.iana.org";

        Console.WriteLine($"查詢 {domain} @ {server} ...");
        string result = Query(server, domain);
        Console.WriteLine(result);
    }

    static string Query(string server, string domain)
    {
        try
        {
            using (var tcp = new TcpClient())
            {
                tcp.Connect(server, 43);
                tcp.ReceiveTimeout = 10000;
                byte[] req = Encoding.ASCII.GetBytes(domain + "\r\n");
                tcp.GetStream().Write(req, 0, req.Length);

                using (var sr = new StreamReader(tcp.GetStream(), Encoding.UTF8))
                    return sr.ReadToEnd();
            }
        }
        catch (Exception ex) { return $"Error: {ex.Message}"; }
    }
}

總結

WHOIS 查詢雖協議簡單,但 TLD 路由、編碼差異、速率限制、非結構化回應解析等工程細節決定了可用性。本文提供從基礎 ASPX 頁面到生產級主控台元件的完整演進路徑,並指向現代 RDAP 協議作為長期演進方向。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved