1.建立socket數組
sk = socket(int family, int type, int protocol);socket
family:協議簇,PF_INET、PF_INET六、PF_PACKET等等。ip
type:類型,SOCK_DGRAM、SOCK_STREAM、SOCK_RAW等等。io
protocol:協議,協議簇上面的協議,這個字段不可使用組合方式,只能使用一個(例如不能使用IPPROTO_UDP|IPPROTO_ICMP)。總結
協議棧收到數據包是從family開始匹配的,以後匹配type,protocol,若是family是PF_PACKET,則繼續匹配protocol(此時沒有類型區分)。數據
2.socket參數組合協議
[1]建立INET TCP/UDP socket:co
socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); //建立UDP socket,第三個參數能夠填0,填0默認是用UDP類型protocol
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); //建立TCPsocket,第三個參數能夠填0,填0默認是用TCP類型參數
收到的爲應用層數據,發送時填充應用層數據。
[2]建立INET RAW socket:
socket(PF_INET, SOCK_RAW, IPPROTO_TCP|IPPROTO_UDP|IPPROTO_ICMP);
收到的是從IP頭開始的數據,發送時從IP協議以後填充,例如UDP協議時填充UDP頭+應用數據,TCP則填充TCP頭+應用數據。
若是設置了IP_HDRINCL選項:setsockopt(sk, IPPROTO_IP, IP_HDRINCL, &option, sizeof(option)),則UDP協議時發送時填充IP頭+UDP頭+應用數據。
socket(PF_INET, SOCK_RAW, IPPROTO_RAW); //收發都是從ip頭開始,等於自動設置IP_HDRINCL選項
[3]建立鏈路層socket:
socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))
收到的是從二層頭開始的完整數據包,當第三個參數是ETH_P_ALL時,能夠接收到從本機發出去的數據包。
socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))
收到的是從二層頭上面開始的數據包。
3.總結
[1]SOCK_RAW類型一般稱爲"原始套接字",這裏的"原始"是相對來講的,例如協議簇是PF_INET時,則原始就是IP層的起始。協議簇是PF_PACKET時,則原始就是二層的起始。