標准套接字分為:
- l 流式套接字(SOCK_STREAM):面向連接的套接字,應用於TCP應用程序。
- l 數據包套接字(SOCK_DGRAM):無連接的套接字,應用於UDP應用程序。
原始套接字:是一種對原始網絡報文進行處理的套接字,主要用途有:
- l 發送自定義的IP數據包
- l 發送ICMP數據包
- l 網卡的偵聽模式,監聽網絡上的數據包
- l 偽裝IP地址
- l 自定位協議的實現
原始套接字主要應用於底層網絡編程,原始套接字與標准套接字之間的關系如下:
原始套接字的創建:
int rawsock = socket(AF_INET,SOCK_RAW,protocol);
常見的協議類型如下:
- l IPPROTO_IP: IP協議,接受或者發送IP數據包,包含IP頭部
- l IPPROTO_ICMP: ICMP協議,接受或者發送ICMP的數據包,IP的頭部不需要處理
- l IPPROTO_TCP: TCP協議,接受或者發送TCP數據包
- l IPPROTO_UDP: UDP協議,接受或者UDP數據包
- l IPPROTO_RAW: 原始IP包。
鏈路層原始套接字
可以直接用於接收和發送鏈路層MAC幀,在發送時需要由調用者自行構造和封裝MAC首部。而網絡層原始套接字可以直接用於接收和發送IP層的報文數據,在發送時,需要自行構造IP報文頭(取決是否設置IP_HEADER選項),另外必須在管理員權限下才能使用原始套接字。
原始套接口提供了普通TCP和UDP的socket不能提供的三種能力:
- l 進程使用raw socket可以讀寫ICMP、IGMP等分組,這個功能還使得使用ICMP或IGMP構造的應用程序能夠完全作為用戶進程處理,而不必往內核中添加額外代碼。
- l 大多數內核只處理IPV4數據包中的一個名為協議的8字段的值1(ICMP)、2(IGMP),6(TCP)、17(UDP)四種情況,然而該字段還有其他值。進程使用raw socket就可以讀寫那些內核不處理IPv數據包。因此,可以使用原始套接字定義自己的協議格式。
- l 通過使用raw socket,進程可以使用IP_HADINCL套接口選項自行定義IP頭部,這個功能可用於構造特定類型的TCP或UDP分組等。
鏈路層原始套接字調用socket()函數創建,第一個 參數指定協議族類型為PF_PACKET,第二個type可以設置為SOCK_RAW或SOCK_DGRAM,第三個參數時協議類型(只對報文接收由意義)。協議類型protocol不同取值的意義如下:
socket(PF_PACKET,type,htons(protocol))
- l 參數type設置為SOCK_RAW時:套接字接收和發送數據都是從MAC首部開始的早發送時需要由調用者從MAC首部開始構造函數和封裝報文數據。該種情況是用於某些項目需要用到自定義的二層報文socket(PF_PACKET,SOCK_RAW,htons(protocol))
- l 參數type設置SOCK_DGRAM時,套接字接收到的數據報文會將MAC首部去掉。同事在發送時也不需要手動構造MAC首部,只需要從IP首部(或ARP首部,取決去封裝的報文類型)開始構造即可。而MAC首部的填充由內核實現。若對於首部不關心的場景,可以使用此類型。socket(PF_PACKET,SOCK_DGRAW,htons(protocol))
protocol不同取值:
protocol |
值 |
作用 |
ETH_P_ALL |
0x0003 |
接收本機收到的所有二層報文 |
ETH_P_IP |
0x0008 |
接收本機收到的所有IP報文 |
ETH_P_ARP |
0x0806 |
接收本機收到的所有ARP報文 |
ETH_P_RARP |
0x8035 |
接收本機收到的所有RARP報文 |
自定義協議 |
比如0x0810 |
接收本機收到的所有類型為0x0810的二層報文 |
不指定 |
0 |
不能用於接收,只能用於發送 |
… |
… |
… |
網絡層原始套接字:
創建面向連接的TCP和創建面向無連接的UDP套接字,在接受和發送時只能操作數據部分,而不能對IP首部或TCP或UDP首部進行操作。如果想要操作IP首部或傳輸層協議首部,就需要調用如下socket()函數創建網絡層原始套接字。
第一個參數指定協議族的類型為PF_INET
第二個參數為SOCK_RAW
第三個參數protocol為協議類型。
- l 接收報文 網絡層原始套接字接收到的報文數據從IP首部開始的,即接收到的數據包含了IP首部,TCP/UDP/ICMP等首部,以及數據部分。
- l 發送報文 網絡層原始套接字發送的報文數據,在默認情況下是從IP首部之后開始的,即需要由調用者自行構造和封裝TCP/UDP等協議首部。這種套接字也提供了發送時從IP首部開始構造數據的功能。通過setsocketopt()個套接字設置上IP_HDRINCL選項,就需要在發送時自行構造IP首部。
protocol |
值 |
作用 |
IPPROTO_TCP |
6 |
接收TCP類型的報文 |
IPPROTO_UDP |
17 |
接收UDP類型報文 |
IPPROTO_ICMP |
1 |
接收ICMP類型報文 |
IPPROTO_IGMP |
2 |
接收IGMP類型報文 |
IPPROTO_RAW |
255 |
不能接收報文,只能發送(需要構造數據包首部) |
IPPROTO_OSPF |
89 |
接收協議號為89的報文 |
… |
… |
… |