原始套接字 IP_HDRINCL

原始套接字能夠訪問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! /n");exit(1);}

  原始套接字直接使用IP協議的套接字,因此是非面向鏈接的。在這個套接字上能夠調用connect和bind函數,分別執行綁定對方和本地地址。

  說明:

  bind函數:調用bind函數後,發送數據包的源IP地址將是bind函數指定的地址。如是不調用bind,則內核將以發接口的主IP地址填充。若是設置了IP_HDRINCL,那麼必須手工填充每一個發送數據包的源IP地址。

  connetc函數:調用connect函數後,能夠用write和send發送數據包。內核將用這個綁定的地址填充IP數據包的目的IP地址。

  發送數據包

  使用原始套接字發送數據包必須遵循如下規則:1.若是沒有用connect函數綁定對方地址時,則應使用sendto或sendmsg函數發送數據包,在函數參數中指定對方地址。如?饔昧薱onnect函數,則能夠直接使用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地址祕須與這它相同網絡

相關文章
相關標籤/搜索