zoukankan      html  css  js  c++  java
  • SOCK_RAW编程

    TCP(SOCK_STREAM)和UDP套接口(SOCK_DGRAM)可以满足大部分需求,但要获取底层协议内容就需要原始套接字。相比前两者,SOCK_RAW具有如下优点:

    1)使用原始套接字可以读写ICMP及ICMP6,如ping程序就是使用原始套接字发送ICMP应答请求。

    2)使用原始套接字可以读写特殊的IP数据包,内核不处理这些数据包的IP协议字段,而出错的诊断将依靠字段的含义。

    3)利用原始套接口设置IP_HDRINCL套接口选项可以构造自己的IP头部。

    创建

    int sockfd=socket(AF_INET, SOCK_RAW, protocol);

    AF_INET:使用IPv4协议

    SOCK_RAW:原始套接字

    protocol:协议名

    建立原始套接口后,可以通过它向网络中写自己的IP数据包,为了防止非法用户破坏网络,规定只有超级用户才有创建原始套接口的权限。

    输入

    内核如何将接收到的分组发送给原始套接字,遵循如下原则:

    》接收到的TCP和UDP分组绝不会传递给任何原始套接子。

    》当内核处理完ICMP消息之后,绝大部分ICMP分组将传递给原始套接口。

    》当内核处理完IGMP消息后,所有IGMP分组将传递给某个原始套接口。

    》所有带有内核不能识别的协议字段的IP数据包都将传递给某个原始套接口,而内核只是检验IP头部中的某些字段。

    如果数据包以分片形式到达,则该分组将在所有分片到达并重组后才传给该套接字。

    输出

    如果套接字没有使用函数connect进行链接,则可以调用函数sendto或sendmsg,他们可以指定目的IP地址。如果已经连接,可以调用write/writev或send。

    如果没有设置IP_HDRINCL选项,则内核写的数据起始地址指IP头部之后的第一个字节,此时内核构造IP头部,并且内核将IP头部的协议段设为用户在调用socket()时指定的protocol参数。

    如果设置IP_HDRINCL选项,则内核写的数据起始地址指向IP头部的第一个字节,用户所提供的数据的大小值必须包括头部的字节数,此时进程构造出以下两项以外的整个IP头部:IP标识字段可以设为0,要求内核设置该值,IP头部的校验由内核来计算和存储。类似TCP协议超出外出接口的分组,内核将其分片。

    匹配

    当内核准备好一个待传输的数据包之后,内核将对所有的进程的原始套接口进行寻找,每个匹配的套接字都将收到一个该IP数据包的复制。匹配的过程分为3个测试步骤,只有3个测试步骤都满足时,数据包才会传递给该套接字。

    》在创建套接字时,如果protocol不为0,则接收到的数据包的协议字段应该与之匹配。

    》如果在原始套接口上绑定一个本地IP地址,那么接收到的数据包的地址应该与之匹配。

    》如果此原始套接字通过调用connect()指定一个对方IP地址,那么接收到的源IP地址应该与之相匹配。

    技巧:如果一个原始套接子创建参数protocol设置为0,并且没有调用connect()和bind(),那么对于内核传递给原始套接子的每个原始数据包,该套接口都会收到一个复制数据包。

    示例

    网上找到一个判断网络是否连通的程序,其通过发送ICMP包来实现。

    参考:

    1. linux环境下C编程指南

    2. linux下判断网络是否连接

  • 相关阅读:
    import和require的区别
    React Native--Animated:`useNativeDriver`is not supported because the native animated module is missing
    XMLHttpRequest
    react-native中更改android/ios的入口文件
    react-native 跳转到ios/android 权限设置界面
    CocoaPods安装和使用
    React、React Native面试题
    UIBarButtonSystemItem 样式
    (转)自定义UITabBar
    ios 代码规范
  • 原文地址:https://www.cnblogs.com/embedded-linux/p/7071643.html
Copyright © 2011-2022 走看看