學習--原始套接字(轉)

ba發表於2007-08-15
學習--原始套接字(轉)[@more@]原始套接字可以訪問ICMP和ICMP等協議包,可以讀寫核心不處理的IP資料包。可以建立自定義的IP資料包首部。一句話,使用原始套接字可以

編寫基於IP協議的通訊程式。

1.建立原始套接字
具體格式如下:
int sockfd;
sockfd = socktet(AF_INET, SOCK_RAW, IPPROTO_ICMP);
第一個引數:協議族 AF_INET 代表TCP/IP協議
第二個引數:SOCKET型別
第三個引數:協議型別
注意:
@如果指定協議為0時,原始套接字可以接收核心傳遞給原始套接字的任何IP資料包,且只有超級使用者才可以建立原始套接字。
@當需要編寫自己的IP資料包首部時,可以在原始套接字上設定套接字選項IP_HDRINCL。在不設定這個選項的情況下,IP協議自動填充IP資料包的首部。

int on = 1;
if(setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0)
{
fprintf(stderr, "setsockopt IP_HDRINCL ERROR! ");
exit(1);
}


原始套接字直接使用IP協議的套接字,所以是非面向連線的。在這個套接字上可以呼叫connect和bind函式,分別執行繫結對方和本地地址。
說明:

bind函式:呼叫bind函式後,傳送資料包的源IP地址將是bind函式指定的地址。如是不呼叫bind,則核心將以發介面的主IP地址填充。如果設定了IP_HDRINCL,那麼必須手工填充每個傳送資料包的源IP地址。

connetc函式:呼叫connect函式後,可以用write和send傳送資料包。核心將用這個繫結的地址填充IP資料包的目的IP地址。

傳送資料包

使用原始套接字傳送資料包必須遵循以下規則:
1.如果沒有用connect函式繫結對方地址時,則應使用sendto或sendmsg函式傳送資料包,在函式引數中指定對方地址。如果呼叫了connect函式,則可以直接使用send,write或writev來傳送資料包。

2.如果沒有設定IP_HDRINCL選項時,包內可寫的內容為資料部分,核心將自動建立IP首部。如果設定了IP_HDRINCL選項,則包內要填充的內容為IP資料包和首部。核心只負責填充下面兩個域:
·如果將IP資料包的標識域設定為0,核心將設定這個域
·核心總是計算和填充IP資料包首部的校驗和。

注意:IP資料包首部各個域的內容都是網路位元組順序。

接收資料包

核心遵循以下規則接收資料包:
1.UDP和TCP資料包從不傳送給一個原始套接字。如果要檢視這兩類資料包,只能透過直接訪問資料鏈路層來實現。
2.大多數ICMP資料包的一個複製傳送給匹配的原始套接字。
3.核心處理的所有其它型別的資料包的一個複製都傳給匹配的原始套接字。
4.所有核心不能識別的協議型別的IP資料包都傳送給匹配的原始套接字。對於這些IP資料包,核心只做必要的檢驗工作。

在將一個IP資料包傳送給原始套接字之前,核心需要選擇匹配的原始套接字
1.資料包的協議域必須與接收原始套接字的協議型別匹配。
2.如果原始套接字呼叫了bind函式繫結了本地IP地址,那麼到達的IP資料包的源IP地址必須和對方的IP相匹配。
3.如果原始套接字呼叫connect函式指定了對方的IP地址,則到達的IP資料包的源IP地址秘須與這它相同。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10617731/viewspace-958639/,如需轉載,請註明出處,否則將追究法律責任。

相關文章