簡體   English   中英

如何比較C中的套接字地址?

[英]How to compare socket address in C?

我的意思是,當我檢查兩個struct sockaddr是否具有相同的 IP 地址和端口號時,我應該比較struct sockaddr哪些字段? 那么sockaddr_in呢?

我可以將sockaddr_insockaddr ,並將其與真正的sockaddr進行比較嗎?

首先,您需要檢查系列(IPv4、IPv6 或其他)。 然后您可以將每個 sockaddr 轉換為適當的“派生”類型,如 sockaddr_in。 看看蘋果是如何做到的: http : //www.opensource.apple.com/source/postfix/postfix-197/postfix/src/util/sock_addr.c

首先,當你處理values 時,你需要使用struct sockaddr_storage ,因為struct sockaddr只對指針是安全的,否則你會遇到大小和對齊問題。

其次, struct sockaddr是在 C 中傳遞的“基類”。 第一個成員是sa_family_t sa_family; (雖然,因為這個struct早於結構成員在單獨的命名空間中,每個“子類”使用一個唯一的前綴(我遇到過至少 40 個子類))。

第三 - 雖然您可能認為每個struct定義都是可靠的,但事實證明類的大小因內核/庫版本而異。 因此,您始終必須將sizeof()傳遞給實際的struct sockaddr_FOO以避免垃圾。 例如,舊版本的struct sockaddr_in6沒有sin6_scope_id成員。

您可能應該將其包裝在一個struct以保持理智(並提供各種輔助功能):

struct SocketAddress
{
    struct sockaddr_storage addr;
    socklen_t addr_len;
};

然后,您的比較代碼如下所示:

// returns < 0 if (left < right)
// returns > 0 if (left > right)
// returns 0 if (left == right)
// Note that in general, "less" and "greater" are not particularly
// meaningful, but this does provide a strict weak ordering since
// you probably need one.
int socket_cmp(struct SocketAddress *left, struct SocketAddress *right)
{
    socklen_t min_addr_len = left->addr_len < right->addr_len ? left->addr_len : right->addr_len;
    // If head matches, longer is greater.
    int default_rv = right->addr_len - left->addr_len;
    int rv = memcmp(left, right, min_addr_len);
    return rv ? rv : default_rv;
}

可是等等! 如果您小心的話,上面的代碼就足夠了,但是小心仍然需要很多細節。 例如:

  • 是否所有的套接字地址都將在您的程序的單次運行中生成,還是會從某些外部介質中讀取? 對於后一種情況,您需要規范化諸如sin6_scope_id類的sin6_scope_id

  • 您是否必須在同一個程序中同時處理 IPv4 和 IPv4-on-IPv6 地址(映射為ffff::1.2.3.4 )? 最簡單的方法是在程序中專門處理 IPv6,因為相關函數也接受 IPv4 地址。 為了獲得最佳可移植性,請務必禁用(使用setsockoptIPV6_V6ONLY標志。 或者,您可以啟用該標志以幫助確保 IPv6 地址從不包含 IPv4 地址。 (請注意, localhost的查找有所不同——但這是所有域查找的普遍問題,可能返回多個結果)。

  • 您需要確保所有結構填充都歸零。

暫無
暫無

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM