帧中继环境下Ping的实现 


 
  

帧中继环境下Ping的实现 


一. ICMP协议和Ping 命令

  为了让互联网中的路由器报告错误或提供有关意外情况的信息,TCP/IP中加入了一个特殊用途的报文机制。这个机制叫做Internet控制报文协议ICMP(Internet Control Message Protocol),它是IP的一部分,并在每个IP实现中必须有它。最初的设计虽然是为了允许路由器向主机报告投递出错的原因,但是ICMP并没有限制仅在路由器上使用。尽管限制某些ICMP报文的使用,但是任一台机器可以向任何其他机器发送ICMP报文。因此,主机可以使用ICMP与路由器或另一台主机通信。
  当一台主机创建了一个I P 数据报时,主机会产生一个覆盖整个头部的校验和。无论何时收到一个数据报,校验和都被用于验证头部是否无损地到达。为了验证校验和,计算机对接收到的数据报的整个头部(包括校验和域)重新计算校验和。如果I P 头部中的某一位在传输过程中被破坏,则计算出的校验和不为零。当改变头部中的域时(例如将生存时间TIME TO LIVE 域递减),路由器必须在转发该数据报前,重新计算校验和。
  发现校验和错时的处理非常简单:数据报必须立即丢弃,而不作进一步的处理。接收者不能相信数据包头部中的任何域,因为接收者不知道哪一位被改变了。甚至也不能发一个出错消息给发送者,因为接收者不能相信包头中的源地址。同样,接收者也不能转发被损坏的数据包,因为它也不能相信包头中的目的地址。因此,接收者除了将被损坏的数据包丢弃外别无选择。
  ICMP报文是放在一个IP数据报的数据部分中通过互联网的。ICMP报文的最终目的不是一个应用程序或是目的机器上的用户,而是该机上处理它的Internet协议软件模块。总之,ICMP在两台机器上的Internet协议软件之间提供了通信。
ICMP中的回送请求(echo request)和回送应答(echo reply)报文为网络管理者或用户提供了一个识别网络问题的调试工具。主机或路由器向指定目的站发送ICMP回送请求报文,任何收到回送请求的机器形成回送应答并把它返回最初的发送者。回送请求包含一个可选数据区;应答包含了在请求中所发送数据的一个拷贝。回送请求及其关联的应答可用来测试目的站是否可达和是否响应。因为请求和应答都是在IP数据报中传送的,所以应答的成功接收就证实传送系统的主要部分是正常的。
  在许多系统上,用户所使用的发送ICMP回送请求的命令叫做Ping。较复杂的Ping的发送一系列ICMP回送请求,捕获响应并提供丢失数据报的统计。不太复杂的版本仅仅发送一个ICMP回送请求并等待应答。

二. IP和ICMP报文格式

  ICMP回送请求和回送应答报文格式如下:
  
  IP报文格式如下:
   

  程序中利用函数CheckSum()来计算和验证IP的首部校验和以及ICMP的校验和。将要计算校验和的数据部分看作为一个16位的整数序列,并定义校验和是数据中所有16位整数的和的二进制反码。在函数CheckSum()中使用了32位(长)算法来累加得到一个和,然后通过向这个整数和中增加所有进位位的方法,将结果折合成一个16位的值。最后,CheckSum()返回结果的反码。注意,每次调用CheckSum()计算校验和之前,要先将校验和域清空,再计算赋值。

三. 程序思路

  该实验的实现是在只是前面提到的ARP/InARP的基础上增加了对Ping的处理,仍然采用多线程结构,实现互斥操作。
  在主线程中,增加了用户可以使用Ping命令,并做出相应处理。写线程仍然是从数据包队列中取出一个数据包,并在写事件到来时将其发送出去。 读线程在读取一个数据包后判断其包类型时,增加了对ICMP回送请求和回送应答的处理。

四. 主要的数据结构

  Ping的实现是ARP/InARP实现的基础上增加了以下一些数据结构:
  struct S_PING_PKT
  
  // 定义了Ping报文的格式,包括帧中继报文头,
  // IP数据报头,ICMP报文格式;
  /
  {
     //FrameRelay head
     unsigned char frameHead[2];

     // IP head
     unsigned char ip_ver; // 0x45
     unsigned char ip_tos; // 0
     unsigned short ip_tl; // 0x0020
     unsigned short ip_id;
     unsigned short ip_ffo; // 0x0000
     unsigned char ip_ttl; // 32
     unsigned char ip_pro; // 1

     unsigned short ip_chk;
     unsigned char ip_sip[4];
     unsigned char ip_tip[4];

     // ICMP head
     unsigned char type; // 8=echo request 0=Echo reply
     unsigned char code; // 0
     unsigned short chk;
     unsigned short id;
     unsigned short seq;

     //可选数据
     unsigned char data[32];
  };

  struct S_pingState; //用于记录发送出去的Ping报文的状态信息,包括Ping的目的IP地址,该报文是否已发送,是否已经接收到应答;

六. 程序结构与主要流程

  (1) 主线程: 接收用户输入,在用户使用Ping命令时,将用户输入的目的IP地址存放到S_pingState结构中去,调用函数SendPing()
  函数SendPing()实现如下: 

  (2) 读线程


函数handlePingRequest():
  生成一个相应的回送请求,并暂存到待发送数据队列中

函数handlePingReply():
  根据收到的应答的序列号,将相应的S_pingState中的已接收标志置为1

七.程序中其他一些处理

  1. 并发控制:由于本程序是一个多线程的程序,多个线程运行时是共享代码和数据的。如果不对这种共享作一些控制的话肯定会出现不可预料的结果。本程序对并发的处理采用 MFC 中的并发锁机制,由于线程会共享的数据被封装在两个类里面(C_QUEUE_INFO和C_DLCI_INFO),线程操作数据都是通过这两个类的实例进行的,所以只要在两个类的代码里实现并发锁就可以了。
  2. 需要特别注意的是数据链路帧的帧头不是固定的,有的情况下(发送配置类原语)是8个字节,真正发送数据的时候是2个字节。
  3. 协议中对数字的处理可能会和大家最初设想的很不一样。譬如主机的IP地址,大家很可能会认为是和标准Socket里面那样是一个以网络字节序存储的结构体来表示的,结果经过分析发现不是,而是用了四个字节,每个字节存储相应的点分十进制数字。如 100.1.1.1 在协议数据包中是这样构成的:[100] [1] [1] [1],其中[ ]表示一个字节。
  4. 校验和的处理也很奇怪。传输时也不是采用网络字节序,而是采用了位串的方式。

参考资料:

RFC791, J. Postel. Internet Protocol, Sep-01-1981.
RFC826, D.C. Plummer. Ethernet Address Resolution Protocol, Nov-01-1982.
RFC1293, T. Bradley, C. Brown, Inverse Address Resolution Protocol. January 1992.
RFC1294, T. Bradley, C.Brown, A. Malis. Multiprotocol Interconnect over Frame Relay. January 1992.
CCITT X.36


附录:

A. 帧中继的一些原语

  #define DL_DATA_IND 4
  #define DL_DATA_REQ 4
  /*
  ID (04)
  DSAP
  USER_DATA
  */
  #define NUM_DL_PARA 12
  #define DL_PARA_REQ 7
  #define DL_PARA_IND 7
  /*
  ID (07)
  DSAP
  ..........
  **********
  PARA
  VALUE_LOW
  VALUE_HIGH
  **********
  ..........
  */
  /* ------------PARA TABLE--------------
  PAR 1: CONFIG
    BIT 0: 1-ON,0-OFF
    BIT 1: 1-LMI:Q.933 Annex A, 0-LMI:NONE
  PAR 2: FIRST_DLCI
  PAR 3: NUM_DLCI
  PAR 4: NUM_PVC
  PAR 5: N203
  PAR 6: N391
  PAR 7: N392
  PAR 8: N393
  PAR 9: T391
  PAR 10: T392
  PAR 11: BAUD RATE
    0---XXX
    1---XXX
    2---XXX
    3---75
    4---150
    5---300
    6---600
    7---1200
    8---2400
    9---4800
    10---9600
    11---19200
    12---48000
    13---64000
    14---128000
    15---256000
  PAR 12:CLOCK 1-INTER; 0-EXTERN */

  CONFIG: 3--使用Q.933协议中附件A的链路管理协议 (缺省值)
       1--不使用上述链路管理协议
  DLCI NUM: 永久虚电路的个数
  FIRST DLCI: 第一条永久虚电路的DLCI编号,缺省为16
  N391: 完全状态(所有PVC状态)轮询计数器
  N392: 差错/恢复计数器(N392应小于或等于N393)。
  N393: 事件监测计数器(如果N393置为一个比N391小很多的值, 则链路可能在差错和无差错状态之间切换而未能被DTE或网络觉察)。
  T391: 链路完整性校验轮询计时器
  T392: 轮询校验计时器

  #define DL_WIND_IND 8
  /*
  ID (08)
  DSAP
  WIND_SIZE
  */

  #define DL_PERMIT_REQ 9
  /*
  ID (09)
  DSAP
  PERMIT_SIZE
  */

  #define DL_STATE_IND 10
  /*
  ID (10)
  DSAP (0)
  STATE
  **********
  DSAP
  DLCI_LOW
  DLCI_HIGH
  STATE : 0---NOT READY 1---READY
  **********
  */

B. 物理层原语

  VL3-X25规程控制卡向高层提供了按X.211建议设计的网络服务原语。当VL3-X25规程控制卡设置成物理模式时可以使用这些原语。VL3规程控制卡原语用VL3规程控制卡驱动程序作为数据块发送和接收。用户把每个原语看成一个数据块,交给VL3规程控制卡驱动程序,VL3规程控制卡控制卡驱动程序也把原语以数据块的形式交给用户。

  PH_ACT_REQ激活请求、PH_ACT_IND激活指示
  格式
    ID  (01)
  说明
    PH_ACT_REQ用于激活物理链路,PH_ACT_IND用于指示物理链路已激活。
PH_DEACT_REQ撤消请求、PH_DEACT_IND撤消指示
  格式
    ID  (02)
  说明
PH_DEACT_REQ用于撤消已激活的物理链路、PH_DEACT_IND用于指示物理链路已撤消。
  PH_DATA_REQ数据请求、PH_DATA_IND数据指示
  格式
    ID  (03)
    USER_DATA
  说明
    PH_DATA_REQ用于发数据,PH_DATA_IND用于指示收到的数据。
   PH_PARA_REQ参数请求、PH_PARA_IND参数指示
  格式
    ID   (04)
    .....................
    *********************
    PARA
    VALUE_LOW
    VALUE_HIGH
    *********************
    .....................
  说明
    PH_PARA_REQ用于设置或读出参数。当原语没有参数字段时从VL3规程控制卡中读出参数。否则设置新的参数值。参数的编号和意义如下表。
  
  
    
 


        
 

转载于:https://www.cnblogs.com/ericgqs/archive/2005/11/09/272634.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值