Linux 原始套接字

2021-06-01 23:24:30 字數 1541 閱讀 8089

原始套接字可以用來自行組裝ip資料報,然後將資料報傳送到其他終端。必須在管理員許可權下才能使用原始套接字。(總結自《unix網路程式設計 卷1:套接字聯網api》)

(1)原始套接字的建立

int sockfd = socket (af_inet, sock_raw, ipproto_***);後面的***可以是icmp,udp,tcp等。

可以在這個套接字上呼叫bind函式,但是比較少見。bind函式僅僅設定本地位址,因為原始套接字不存在埠的概念。就輸出而言,呼叫bind設定的是將用於從這個原始套接字傳送的所有資料報源ip位址。如果不呼叫bind,核心就把源ip位址設定為外出介面的主ip位址。

(2)原始套接字的輸出

如果ip_hdrincl套接字選項未開啟,那麼由程序讓核心傳送的資料的起始位置指的是ip首部之後的第乙個位元組,因為核心將構造ip首部並把它置於來自程序的資料之前。核心把所有構造ipv4首部的協議字段設定成來之sock呼叫的第三個引數。

如果ip_hdrincl套接字選項已開啟,那麼由程序讓核心傳送的資料的起始位置指的是ip首部的第乙個位元組。程序呼叫輸出函式寫出的資料量必須包括ip首部的大小。整個ip首部都是由程序構造,不過ip的標識字段可以設定為0,從而告知核心設定該值ipv4首部校驗和字段總是由核心計算並儲存,ipv4的選項欄位是可選的。

核心會對超出外出介面mtu的原始分組進行分片。

開啟ip_hdrincl的**是

const int on =1;

if (setsockopt (sockfd, ipproto_ip, ip_hdrincl, &on, sizeof(on)) < 0)

錯誤處理;

(3)原始套接字的輸入

首先要考慮核心將哪些接收到的ip資料報傳遞到原始套接字?這要遵循下面的規則

a:接收到的udp或者tcp分組絕不傳遞到任何原始套接字,如果乙個程序想要讀取含有udp分組或tcp分組的ip資料報,它就必須在資料鏈路層讀取這些分組。

b:大多數icmp分組在核心處理完其中的icmp訊息後傳遞到原始套接字。igmp亦是如此。

d:如果某個資料報以片段的形式到達,那麼在它的所有片段均到達且重組出該資料報之前,不傳遞任何片段分組給原始套接字。

當核心有乙個需要傳遞到原始套接字的資料報時,它將檢查所有程序上的所有原始套接字,以尋找所有匹配的套接字。每個匹配的套接字將被傳遞送以該ip資料報的乙個副本。核心對每個原始套接字均執行以下3個測試,只有這三個測試均為真,核心才把接收到的資料報傳送給這個套接字。

a:如果建立這個原始套接字時指定了非0的協議引數(socket的第三個引數),那麼接收到的資料報協議字段必須匹配該值。

注意,如果乙個原始套接字是以0值協議引數傳遞的,並且沒有呼叫bind,connect,那麼該套接字將接收可由核心傳遞到原始套接字的每個原始資料報的乙個副本。

而且無論何時往乙個原始ipv4套接字上遞送乙個ip資料報,傳遞到該套接字所在程序的都是包括ip首部在內的完整資料報,然後對於ipv6原始套接字,傳遞套接字的只是扣除了ipv6首部和所有擴充套件首部的payload。

linux原始套接字

通常情況下程式設計師接所接觸到的套接字 socket 為兩類 1 流式套接字 sock stream 一種面向連線的 socket,針對於面向連線的tcp 服務應用 2 資料報式套接字 sock dgram 一種無連線的 socket,對應於無連線的 udp 服務應用。從使用者的角度來看,sock ...

原始套接字

資料出處 實際上,我們常用的網路程式設計都是在應用層的報文的收發操作,也就是大多數程式設計師接觸到的流式套接字 sock stream 和資料報式套接字 sock dgram 而這些資料報都是由系統提供的協議棧實現,使用者只需要填充應用層報文即可,由系統完成底層報文頭的填充並傳送。然而在某些情況下需...

原始套接字

參考1 原始套接字能幹什麼?參考2 原始套接字抓包實踐 參考3 各層頭結構 通過原始套接字,我們可以抓取所有傳送到本機的ip包 包括ip頭和tcp udp icmp包頭 也可以抓取所有本機收到的幀 包括資料鏈路層協議頭 普通的套接字無法處理icmp igmp等網路報文,而sock raw可以。利用原...