socket 的一些引數

2021-05-22 19:40:36 字數 2583 閱讀 4555

sock_raw(注意一定要在root下使用)原始套接字程式設計可以接收到本機網絡卡上的資料幀或者資料報,對與監聽網路的流量和分析是很有作用的.一共可以有3種方式建立這種socket

1.socket(af_inet, sock_raw, ipproto_tcp|ipproto_udp|ipproto_icmp)傳送接收ip資料報,不能用ipproto_ip,因為如果是用了ipproto_ip,系統根本就不知道該用什麼協議。

2.socket(pf_packet, sock_raw, htons(eth_p_ip|eth_p_arp|eth_p_all))傳送接收乙太網資料幀

3.socket(af_inet, sock_packet, htons(eth_p_ip|eth_p_arp|eth_p_all))過時了,不要用啊

理解一下sock_raw的原理, 比如網絡卡收到了乙個 14+20+8+100+4(乙太網頭+ip頭+udp頭+資料+crc) 的udp的乙太網資料幀.

首先,網絡卡對該資料幀進行硬過濾(根據網絡卡的模式不同會有不同的動作,如果設定了promisc混雜模式的話,則不做任何過濾直接交給下一層輸 入例程,否則非本機mac或者廣播mac會被直接丟棄).按照上面的例子,如果成功的話,會進入ip輸入例程.但是在進入ip輸入例程之前,系統會檢查系 統中是否有通過socket(af_packet, sock_raw, ..)建立的套接字.如果有的話並且協議相符,在這個例子中就是需要eth_p_ip或者eth_p_all型別.系統就給每個這樣的socket接收緩 沖區傳送乙個資料幀拷貝.然後進入下一步.

其次,進入了ip輸入例程(ip層會對該資料報進行軟過濾,就是檢查校驗或者丟棄非本機ip或者廣播ip的資料報等,具體要參考源**),例子 中就是如果成功的話會進入udp輸入例程.但是在交給udp輸入例程之前,系統會檢查系統中是否有通過socket(af_inet, sock_raw, ..)建立的套接字.如果有的話並且協議相符,在這個例子中就是需要ipproto_udp型別.系統就給每個這樣的socket接收緩衝區傳送乙個資料 幀拷貝.然後進入下一步.

最後,進入udp輸入例程 ...

ps:如果校驗和出錯的話,核心會直接丟棄該資料報的.而不會拷貝給sock_raw的套接字,因為校驗和都出錯了,資料肯定有問題的包括所有資訊都沒有意義了.

進一步分析他們的能力.

1. socket(af_inet, sock_raw, ipproto_udp);

能:該套接字可以接收協議型別為(tcp udp icmp等)發往本機的ip資料報,從上面看的就是20+8+100.

不能:不能收到非發往本地ip的資料報(ip軟過濾會丟棄這些不是發往本機ip的資料報).

不能:不能收到從本機傳送出去的資料報.

傳送的話需要自己組織tcp udp icmp等頭部.可以setsockopt來自己包裝ip頭部

這種套接字用來寫個ping程式比較適合

2. socket(pf_packet, sock_raw, htons(x)); 

這個套接字比較強大,建立這種套接字可以監聽網絡卡上的所有資料幀.從上面看就是20+20+8+100.最後乙個乙太網crc從來都不算進來的,因為核心已經判斷過了,對程式來說沒有任何意義了.

能: 接收發往本地mac的資料幀

能: 接收從本機傳送出去的資料幀(第3個引數需要設定為eth_p_all)

能: 接收非發往本地mac的資料幀(網絡卡需要設定為promisc混雜模式)

協議型別一共有四個

eth_p_ip  0x800      只接收發往本機mac的ip型別的資料幀

eth_p_arp 0x806      只接受發往本機mac的arp型別的資料幀

eth_p_arp 0x8035     只接受發往本機mac的rarp型別的資料幀

eth_p_all 0x3        接收發往本機mac的所有型別ip arp rarp的資料幀, 接收從本機發出的所有型別的資料幀.(混雜模式開啟的情況下,會接收到非發往本地mac的資料幀)

傳送的時候需要自己組織整個乙太網資料幀.所有相關的位址使用struct sockaddr_ll 而不是struct sockaddr_in(因為協議簇是pf_packet不是af_inet了),比如傳送給某個機器,對方的位址需要使用struct sockaddr_ll.

在使用sock_raw, sock_dgram和sock_packet的區別(詳請參考

在socket的第乙個引數使用pf_packet的時候,上述三種socket的型別都可以使用。但是有區別。

(1)使用sock_raw傳送的資料必須包含鏈路層的協議頭,接受得到的資料報,包含鏈路層協議頭。而使用sock_dgram則都不含鏈路層的協議頭。

(2)sock_packet也是可以使用的,但是已經廢棄,以後不保證還能支援,不推薦使用。

(3)在使用sock_raw或sock_dgram和sock_packet時,在sendto和recvfrom中使用的位址型別不同,前兩者使用sockaddr_ll型別的位址,而後者使用sockaddr型別的位址。

(4)如socket的第乙個引數使用pf_inet,第二個引數使用sock_raw,則可以得到原始的ip包。

這種socket大小通吃,強悍

socket 的一些麻煩

在vs2010 上面倒是可以編譯的源 但是換到2008上,編譯就出現了如下錯誤資訊。sockaddr in 未宣告的識別符號 包含的標頭檔案是windows.h 最後還是有了結果,就是 在 sockaddr in 的前頭 加上 struct.還有錯誤 error c2275 socket 將此型別用...

關於Socket的一些概念

對於 tcp ip 我們還知道 tcp和 udp,前者可以保證資料的正確和可靠性,後者則允許資料丟失。最後,我們還知道,在建立連線前,必須知道對方的 ip位址和埠號。除此,普通的程式設計師就不會知道太多了,很多時候這些知識已經夠用了。最多,寫服務程式的時候,會使用多執行緒來處理併發訪問。我們還知道如...

socket的一些基本結構

socket的一些基本結構 一 socket的一些基本結構 struct in addr struct sockaddr in 二 socket的一些輔助函式 1 位元組序轉換函式 htons host to network byte order short unsigned integer hto...