zoukankan      html  css  js  c++  java
  • raw_socket(原始套接字)以及普通socket使用终极总结

     

    一、传输层socket(四层socket,普通socket)

    可参考本人以下博客:

    Windows Socket编程之UDP实现大文件的传输:http://blog.csdn.net/luchengtao11/article/details/71016222

    Windows Socket编程之TCP实现大文件的传输:http://blog.csdn.net/luchengtao11/article/details/71012580

    (1)创建

    1.  
      socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//TCP
    2.  
      //或者
    3.  
      socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);//UDP

    AF_INEF表示TCP/IP族

    第三个参数可以为0,由操作系统自行选择

    (2)发送

      sendto(sd,buffer,BUFSIZ,0,(SOCKADDR*)&addrServ,sizeof(SOCKADDR));//UDP
     
      send(sd, buffer, BUFSIZ, 0);  //TCP
     

    (3)接收

    recvfrom(sd,buffer,BUFSIZ,0,(SOCKADDR*)&addrClient,sizeof(SOCKADDR));//UDP
     
    recv(sd, buffer, BUFSIZ, 0);//TCP
    
     

    sd为socket标识符,buffer为接受/发送缓冲区,BUFSIZ为接受/发送缓冲区。后两个参数为发送或接受的对方地址,可以为NULL

    二、网络层socket(三层socket)

    可以参考本人一下博客或代码:

    Linux下的raw Socket(原始套接字)编程:http://blog.csdn.net/luchengtao11/article/details/73878760

    网络层多线程收发:https://github.com/Wuchenwcf/MyCode/blob/master/C%2B%2B/Linux/computer%20network/raw_socket_%E7%BD%91%E7%BB%9C%E5%B1%82%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%94%B6%E5%8F%91.cpp

    (1)创建

    socket(AF_INET, SOCK_RAW, IPPROTO_UDP );//第三个参数可以是UDP,TCP或者ICMP
     

    (2)接收

    recvfrom(sd, buffer, sizeof(buffer), 0,(struct sockaddr *)&client_addr, &addrlen));// 
     

    后两个参数可以为null

    接受的报文是从IP数据报的第一个字节开始的。

    当内核有一个需要传递到原始套接字的IP数据报时,它将检查所有进程上的原始套接字,以寻找所有匹配的套接字。每个匹配懂得套接字将被递送以该iP数据报的一个副本。(事实证明,如果进程过多,匹配的套接字过多,内核会忙于数据报的软过滤和分发,而实际的套接字却空闲,导致性能下降
    内核对每个原始套接字均执行如下3个测试,只有这三个测试为真,内核才把接收到的数据报递送到这个套接字。

    【1】如果创建这个套接字时制订了非0的协议参数(socket的第三个参数),那么接受到的数据报的协议字段必须匹配该值,否则数据报不递送到这个套接字

    【2】如果这个原始套接字已由bind调用绑定了某个本地IP地址,那么接受到的数据报的目的IP地址必须匹配这个绑定的地址,否则该数据报不递送到这个套接字。

    【3】如果这个原始套接字已由connect调用指定了某个外地IP地址,那么接受到的数据报的源IP地址必须匹配这个已连接地址,否则该数据报不递送到这个套接字。

    注意,如果一个原始套接字以0值协议参数创建的,而且没有bind和connect,那么该套接字将接收可由内核传递到原始套接字的每个原始数据报的一个副本。

    (3)发送

    1.  
      /*
    2.  
      如果IP_HDRINCL未开启,由进程让内核发送的数据是从IP首部之后的第一个字节开始的,内核会自动构造合适的IP
    3.  
      如果IP_HDRINGL开启,进程需要自行构造IP包
    4.  
      */
    5.  
      /*
    6.  
      if (setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(int)))
    7.  
      {
    8.  
      perror("setsockopt() error");
    9.  
      exit(-1);
    10.  
      }
    11.  
      */
    12.  
      sendto(sd, buffer, request_length, 0, (sockaddr *)&client_addr, addrlen);

    三、数据链路层scoket(二层socket)

    代码可以参考:

    raw_socket_数据链路层收发实例:https://github.com/Wuchenwcf/MyCode/blob/master/C%2B%2B/Linux/computer%20network/raw_socket_%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82%E6%94%B6%E5%8F%91%E5%AE%9E%E4%BE%8B.cpp
     

    (1)创建

    sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));//第三个参数可以为ETH_P_ALL ETH_P_IP ETH_P_ARP等
     

    (2)接受

    1.  
      struct sockaddr_ll client;
    2.  
      socklen_t addr_length = sizeof(sockaddr_ll);
    3.  
      recvfrom(sock, buffer, 2048, 0, (sockaddr *)&client, &addr_length);//此时的地址是数据链路层的地址


    接受的报文是从以太网的帧开始的

    (3)发送

    sendto(sock, sendbuffer, n, 0, (struct sockaddr *) &client, sizeof(client));
     

    四、小结

    引用:http://blog.csdn.net/firefoxbug/article/details/7561159

         网卡对该数据帧进行硬过滤(根据网卡的模式不同会有不同的动作,如果设置了promisc混杂模式的话,则不做任何过滤直接交给下一层输入例程,否则非本机mac或者广播mac会被直接丢弃).按照上面的例子,如果成功的话,会进入ip输入例程.但是在进入ip输入例程之前,系统会检查系统中是否有通过socket(AF_PACKET, SOCK_RAW, ..)创建的套接字.如果有的话并且协议相符,在这个例子中就是需要ETH_P_IP或者ETH_P_ALL类型.系统就给每个这样的socket接收缓冲区发送一个数据帧拷贝.然后进入下一步.

      其次,进入了ip输入例程(ip层会对该数据包进行软过滤,就是检查校验或者丢弃非本机ip或者广播ip的数据包等,具体要参考源代码),例子中就是如果成功的话会进入udp输入例程.但是在交给udp输入例程之前,系统会检查系统中是否有通过socket(AF_INET, SOCK_RAW, ..)创建的套接字.如果有的话并且协议相符,在这个例子中就是需要IPPROTO_UDP类型.系统就给每个这样的socket接收缓冲区发送一个数据帧拷贝.然后进入下一步。

    最后,进入udp输入例程 ...

    ps:如果校验和出错的话,内核会直接丢弃该数据包的.而不会拷贝给sock_raw的套接字,因为校验和都出错了,数据肯定有问题的包括所有信息都没有意义了.

  • 相关阅读:
    js 工厂模式、简单模式、抽象模式
    Angular 框架介绍
    Node.js从入门到实战ECMAScript6一页纸总结(很大的一页纸)
    ECMAScript 5和ECMAScript6的新特性以及浏览器支持情况
    JSONP 教程
    jQuery ajax() 方法
    AJAX异步的 JavaScript
    自动化构建工具--gulp的初识和使用
    front-end 前端发展学习路线参考图
    Webpack 常用命令总结以及常用打包压缩方法
  • 原文地址:https://www.cnblogs.com/h2zZhou/p/10488628.html
Copyright © 2011-2022 走看看