导航

套接字

Posted on 2018-10-24 16:07  困或  阅读(1178)  评论(0编辑  收藏  举报

1.创建socket

  sk = socket(int family, int type, int protocol);

  family:协议簇,PF_INET、PF_INET6、PF_PACKET等等。

  type:类型,SOCK_DGRAM、SOCK_STREAM、SOCK_RAW等等。

  protocol:协议,协议簇上面的协议,这个字段不可以使用组合方式,只能使用一个(例如不能使用IPPROTO_UDP|IPPROTO_ICMP)。

  协议栈收到数据包是从family开始匹配的,之后匹配type,protocol,如果family是PF_PACKET,则继续匹配protocol(此时没有类型区分)。

2.socket参数组合

  [1]创建INET TCP/UDP socket:

    socket(PF_INET,  SOCK_DGRAM,  IPPROTO_UDP);   //创建UDP socket,第三个参数可以填0,填0默认是用UDP类型

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