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时,则原始就是二层的起始。