zoukankan      html  css  js  c++  java
  • UNP总结 Chapter 26~29 线程、IP选项、原始套接字、数据链路访问

     此为UNP最后一段总结 Chapter30主要为代码实践 请参考UNP

    一、线程

    这里UNP的线程与APUE中讲得线程基本一致,但是APUE讲得更加细致,所以这里只列出主要内容(线程数据会稍微详细) 详细见APUE线程相关章节 或者本博文中的APUE专题

    1.基本线程函数:创建与终止

    2.线程特定数据

    使用线程特定数据是使现成函数线程安全的常用技巧

    这里重点提一下的是

    1).每个系统支持有限数量的线程特定数据项。系统(很可能是线程库)为每个进程维护一个数据结构,我们称之为Key结构,如下图

    2).Key结构中的标志指示这个数组元素是否正在使用,所有的标志初始化为"不在使用"。当一个线程调用pthread_key_create创建一个新线程特定数据项时,系统搜索其Key结构数组并找到第一个未被使用的项。其下标(0~127)称做键(key),这个下标返回给调用线程。我们很快谈到Key结构的另一个成员“析构函数指针”。

    除了进程范围内的Key结构数组外,系统还为进程的每个线程维护多条信息。这些特定于线程的信息我们称之为Pthread结构,其部分内容是我们称之为pkey数组的一个128个元素的指针数组,如下图:

    3).下图给出示意图:把malloc到的内存区和线程特定数据指针相关联

    4).线程n初始化它的线程特定数据后的数据结构

    3.互斥锁

    4.条件变量

    二、IP选项

    1.概述

    IPv4允许在20字节首部固定部分之后跟以最多40字节的选项。尽管已经定义的IPv4选项公有10种,最常用的是源路径选项,这些选项的访问途径是存取IP_OPTIONS套接字选项。

    IPv6允许在固定长度40字节IPv6头部和传输层头部(如ICMPv6,TCP或UDP)之间出现扩展头部(extension header)。和IPv4不同的是,访问IPv6扩展头部的途径是通过函数接口进行,而不是强迫用户去理解头部如何出现在IPv6分组中的真实细节。

    2.IPv4选项、IPv4源路径选项

    1).读取和设置IP选项字段使用getsockopt和setsockopt(level参数为IPPROTO_IP,optname参数为IP_OPTIONS)。getsockopt和setsockopt的第四个参数是指向一个缓冲区(大于小于等于44字节)的指针,第五个参数是该缓冲区的大小。

    2).使用setsockopt设置了IP选项之后,在相应套接字发送的所有IP数据报都将包括这些选项。套接字可以是TCP,UDP或原始IP套接口。为了清除这些选项,可以调用setsockopt,置第四个参数为空指针,或者置第五个参数(长度)为0

    3).当调用getsockopt获取一个由accept创建的已连接TCP套接字的IP选项时,返回的是在相应监听套接字上收到的客户的SYN中源路径选项的逆转。源路径自动被TCP倒序,因为由客户指定的是从客户到服务器的源路径,服务器需要在发送到客户的数据中使用该路径的逆转

    4).源路径是由IP数据报的发送者指定的一个IP地址列表。如果源路径是严格的(strict),那么数据报必须且只能逐一经过所列的节点。如果源路径是宽松的(loose),数据报必须逐一经过所列的节点,不过也可以经过未在源路径中列出的节点。

    下图展现向内核的源路径

    下图展现getsockopt返回的源路径选项格式

    详细代码示例参见UNP

    3.IPv扩展首部

    • 步跳(hop_by_hop)选项必须紧跟40字节的IPv6头部。目前没有定义这种可供应用程序使用的选项。
    • 目的(destination)选项:目前没有定义这种可供应用程序使用的选项。
    • 路由头部(routing header):这是一个源路由选项,在概念上类似于我们在24.3节中描述的IPv4源路径选项。
    • 分片头部(fragmentation hearder):该头部由将IPv6数据报分片的主机自动生成,有最终的目的主机重组片段时处理。
    • 认证头部(authentication header, AH):
    • 封装安全有效负载(encapsulating security payload, ESP)头部:

    4.IPv6路由首部

    下图展现IPv6路由首部:

    5.IPv6粘附选项

    • IPv6分组信息
    • 外出跳限干或跳限
    • 下一条地址
    • 外出流通类别或者接受流通类别
    • 步跳选项
    • 目的地选项
    • 路由首部

    三、原始套接字

    1.概述

    原始套接口提供以下三种TCP及UDP套接口一般不提供的功能。

    1). 有了原始套接字,进程可以读写ICMPv4,IGMPv4,ICMPv6分组。例如:Ping程序,就使用原始套接字发送ICMP回射请求,并接受ICMP回射应答。

    2). 有了原始套接字,进程可以读写内核不处理其协议字段的IPv4数据报。

    3). 有了原始套接字,进程还可以利用IP_HDRINCL套接字选项可以构造自己的IPv4首部。

    2.原始套接字创建

    创建一个原始套接字涉及以下几步:

    1). 当第二个参数是SOCK_RAW时,调用socket函数,以创建一个原始套接字。第三个参数(协议)一般不应为0,例如,为了创建一个IPv4原始套接口,我们可以这样写:

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

    其中protocol参数值为形如IPPROTO_xxx的常值,由<netinet/in.h>头文件定义,如IPPROTO_IGMP

    2).可以设置IP_HDRINCL套接字选项:

    const int on = 1;
    if ( setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0 )
           出错处理

    3).可以在这个原始套接字上调用bind函数,不过不过比较少见。bind函数仅用来设置本地地址:因为原始套接字不存在端口号的概念。就输出而言,调用bind设置的是将用于从这个原始套接字发送的所有数据的源IP地址(只在IP_HDRINCL套接字选项未开启的前提下),若果不调用bind,内核就把IP地址设置为外出接口的主IP地址。

    4).可以在这个原始套接字上可调用connect函数,不过也比较少见。connect函数仅仅设置外地地址,同样因为因为原始套接字不存在端口号的概念。对于输出而言,调用connect之后,我们可以把sendto调用改为write或send调用,因为目的IP地址已经指定了。

    3.原始套接字输出

    原始套接字的输出遵循以下规则:

    1). 普通输出通过调用sendto或sendmsg并指定目的IP地址来完成。如果套接字已经连接,那么也可以调用write,writev或send

    2). 如果IP_HDRINCL选项未开启,那么由进程让内核发送的数据的起始地址指的IP首部之后的第一个字节。因为内核将构造IP首部并把它置于来自进程的数据之前,内核把IPv4首部的协议字段设置成来自socket调用的第三个参数。

    3). 如果IP_HDRINCL铜戒指选项已开启,那么由进程让内核写的数据起始地址指IP首部的第一个字节。

    4). 内核会对超出外出接口MTU的原始分组执行分片。

    4.原始套接字输入

    内核把收到的IP数据报传递到原始套接字要遵循规则:

    • 接收到的TCP分组和UDP分组决不会传递给任何原始套接字
    • 大多数ICMP分组在内核处理完其中的ICMP消息后传递到给原始套接字
    • 所有IGMP分组在内核完成处理其中的IGMP消息之后传递到原始套接口字
    • 内核不认识其协议字段的IP数据报传递到原始套接字
    • 如果某个数据报以片段形式到达,则该分组将在所有片段到达并重组后才传给原始套接字。

    5.ping程序

    ping程序的操作非常简单,往某个IP地址发送一个ICMP回射请求,该节点则以一个ICMP回射应答,概貌如下 程序详见UNP

    6.traceroute程序

    traceroute的用途是确定从我们的主机到目的地之间IP数据报行进的路径,traceroute使用IPv4的TTL字段或IPv6的跳限字段以及两个ICMP消息。它一开始向目的主机发送一个TTL(或跳限)为1的UDP数据报。这个数据报导致头一跳的路由器返回一个“time exceeded in transmit(传输中超时)”错。接着每次对TTL加1,并分别发出UDP数据报,这样可以逐步确定下一个路由器。当UDP数据报终于到达目的主机时,希望目的主机能返回一个“port unreachable(端口不可达)”错,这通过向一个期望未被使用的随机端口发送UDP数据报来实现

    7.一个ICMP消息守护程序

    这里给出描述图 代码见UNP

    从icmpd获取绑定在那个UDP套接字上的端口号之后就关闭该套接字的本地副本后,icmpd一旦收取由该应用进程通过绑定在它的UDP套接字上的端口发送的UDP数据报所引发的ICMP错误,就通过Unix域连接向该应用程序发送一条信息。

    四、数据链路访问

    这里仅列出主要内容

    1.BPF:BSD分组过滤器

    2.DLPI:数据链路提供接口

    3.Linux:SOCK_PACKET和PF_PACKET

    4.libpcap:分组捕获函数库

    5.libnet:分组构造与输出函数库

    6.检查UDP的校验与字段

  • 相关阅读:
    为什么说性别字段不适合做索引?
    过程数据的记录(事务问题)
    两个系统操作同一条表记录涉及的事务的坑(依护系统)
    mybatis插件自动生成代码报错。
    ORACLE使用plsql和其他工具进行表结构和数据迁移
    ORACLE获取建表SQL
    学习英语的技巧
    Oracle的用户管理
    Jmeter做压力测试
    强烈推荐(原创亲测)!!!Fiddler抓取https设置详解(图文)
  • 原文地址:https://www.cnblogs.com/biyeymyhjob/p/2627179.html
Copyright © 2011-2022 走看看