簡體   English   中英

奇怪的Linux套接字協議行為

[英]Strange Linux socket protocols behaviour

對於使用socket()時Linux上的協議定義之間的差異,我有些困惑。 我試圖使用socket(PF_INET, SOCK_STREAM, proto)偵聽TCP上的連接,在我看來, proto存在爭議,或者至少看起來很奇怪。

<netinet/in.h>

...
IPPROTO_IP = 0,    /* Dummy protocol for TCP.  */
...
IPPROTO_TCP = 6,       /* Transmission Control Protocol.  */
...

同意/etc/protocols

ip      0       IP              # internet protocol, pseudo protocol number
hopopt  0       HOPOPT          # hop-by-hop options for ipv6
...
tcp     6       TCP             # transmission control protocol
...

我從網上教程中學, 從該名男子頁tcp(7)您在使用初始化TCP套接字

tcp_socket = socket(AF_INET, SOCK_STREAM, 0);

它絕對可以正常工作,並且肯定一個TCP套接字。 使用上述參數初始化套接字的一件事是該代碼

struct timeval timeout = {1, 0};
setsockopt(tcp_socket, 0, SO_RCVTIMEO, &timeout, sizeof(timeout); // 1s timeout
// Exactly the same for SO_SNDTIMEO here

精絕,但替換所有協議參數(包括后沒有工作的socket()IPPROTO_TCP ,而不是IPPROTO_IP他們有,如上述。

因此,在嘗試了差異之后,我需要問一些搜索問題:

  1. 為什么當我用IPPROTO_TCP替換所有協議參數時,設置協議0顯然只是一個“虛擬” TCP時,設置超時時會出現錯誤92(“協議不可用”)?
  2. 為什么從協議隱式知道(總是?) socket()應該是流,數據報還是原始套接字的信息,反之亦然? (即,TCP是流協議,UDP是數據報協議,...)
  3. “虛擬TCP”可能意味着什么?
  4. 什么是hopopt ,為什么它的協議號與'ip'相同?

非常感謝。

socket提供0協議只是意味着您要為family / socktype對使用默認協議。 在這種情況下,它是TCP,因此得到的結果與IPPROTO_TCP相同。

您的錯誤是在setsockopt調用中。 正確的是

setsockopt(tcp_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); // 1s timeout

0不是協議,而是選項級別。 IPPROTO_TCP是另一個選項級別,但是您不能將其與SO_RCVTIMEO結合使用。 它只能與SOL_SOCKET一起使用。 IPPROTO_TCP一起使用的是tcp(7)中列出的那些,例如TCP_NODELAY

socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 應該工作正常。

作為協議傳遞0只是意味着,請給我默認值。 當處理IP時,在每個系統上哪個是用於流套接字的TCP和用於數據報套接字的UDP。 但是socket()可以用於許多其他事情,而不會給您提供TCP或UDP套接字。

socket()本質上是非常通用的。 socket(AF_INET, SOCK_STREAM, 0); 讀為 “給我IP協議系列中的流式套接字”。 傳遞0表示您對哪種協議沒有偏好-盡管TCP對於任何系統都是顯而易見的選擇。 但從理論上講,它可以為您提供SCTP套接字。

協議隱含數據報或流套接字。 除了基於IP的協議外,還有更多協議,並且許多協議可以用於數據報或流模式,例如SS7網絡中使用的SCCP。

對於基於IP的協議,SCTP可以以基於數據報或流方式使用。 因此套接字(AF_INET,IPPROTO_SCTP); 會模棱兩可。 對於數據報套接字,還有其他選擇,UDP,DCCP,UDPlite。

插座(AF_INET,SOCK_SEQPACKET,0); 是另一個有趣的選擇。 它不能返回TCP套接字,TCP不是基於數據包的。 它不能返回並且使用UDP套接字,UDP無法保證順序傳送。 但是,如果系統支持,則SCTP套接字可以。

我沒有解釋為什么有人在linux netinet / in.h中發表評論“ dummy TCP”

hopopt是“按跳的IPv6 HOP”選項。 在IPv6中,協議鑒別符字段也用作擴展機制。 在IPv4數據包中,有一個協議字段,它是協議標識符,如果該IPv4數據報帶有TCP,則將其設置為IPPROTO_TCP。 如果該IPv4數據包還包含一些其他信息(選項),則它們將通過其他機制進行編碼。

IPv6的操作與此不同,如果有擴展名(選項),則該擴展名將在協議字段中進行編碼。 因此,如果IPv6數據包需要逐跳選項,則將IPPROTO_HOPOPTS放在協議字段中。 實際的逐跳選項還具有協議區分符,該協議區分符指示下一個協議是什么-可能是IPPROTO_TCP或另一個選項。

暫無
暫無

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

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