楼主: keaide

透析ICMP协议

[复制链接]
论坛徽章:
456
ITPUB年度最佳版主
日期:2011-12-28 15:24:18马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14ITPUB年度最佳版主
日期:2014-02-19 10:05:27优秀写手
日期:2013-12-18 09:29:09ITPUB社区千里马徽章
日期:2013-06-09 10:15:34ITPUB年度最佳版主
日期:2013-01-30 17:30:25版主9段
日期:2012-07-03 02:21:03
11#
 楼主| 发表于 2006-7-19 17:24 | 只看该作者
// ICMP 包头(实际的包不包括timestamp字段,
// 作者用来计算包的回应时间,其实完全没有必要这样做)
struct ICMPHeader {
    BYTE type;          // ICMP packet type
    BYTE code;          // Type sub code
    USHORT checksum;
    USHORT id;
    USHORT seq;
    ULONG timestamp;    // not part of ICMP, but we need it
};


extern USHORT ip_checksum(USHORT* buffer, int size);
extern int setup_for_ping(char* host, int ttl, SOCKET& sd,  sockaddr_in& dest);
extern int send_ping(SOCKET sd, const sockaddr_in& dest, ICMPHeader* send_buf, int packet_size);
extern int recv_ping(SOCKET sd, sockaddr_in& source, IPHeader* recv_buf,
        int packet_size);
extern int decode_reply(IPHeader* reply, int bytes, sockaddr_in* from);
extern void init_ping_packet(ICMPHeader* icmp_hdr, int packet_size, int seq_no);

/*
* 程序名: rawping.cpp
* 说明:   
*       主要函数库实现部分
*/

include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream.h>
#include "rawping.h"

// 计算ICMP包的校验和的简单算法, 很多地方都有说明, 这里没有必要详细将
// 只是一点要提, 做校验之前, 务必将ICMP包头的checksum字段置为0
USHORT ip_checksum(USHORT* buffer, int size)
{
    unsigned long cksum = 0;
   
    // Sum all the words together, adding the final byte if size is odd
    while (size > 1) {
        cksum += *buffer++;
        size -= sizeof(USHORT);
    }
    if (size) {
        cksum += *(UCHAR*)buffer;
    }

    // Do a little shuffling
    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >> 16);
   
    // Return the bitwise complement of the resulting mishmash
    return (USHORT)(~cksum);
}

//初试化RAW Socket, 设置ttl, 初试化dest
// 返回值 <0 表失败

int setup_for_ping(char* host, int ttl, SOCKET& sd, sockaddr_in& dest)
{
    // Create the socket
    sd = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, 0, 0, 0);
    if (sd == INVALID_SOCKET) {
        cerr << "Failed to create raw socket: " << WSAGetLastError() <<
                endl;
        return -1;
    }

    if (setsockopt(sd, IPPROTO_IP, IP_TTL, (const char*)&ttl,
            sizeof(ttl)) == SOCKET_ERROR) {
        cerr << "TTL setsockopt failed: " << WSAGetLastError() << endl;
        return -1;
    }

    // Initialize the destination host info block
    memset(&dest, 0, sizeof(dest));

    // Turn first passed parameter into an IP address to ping
    unsigned int addr = inet_addr(host);
    if (addr != INADDR_NONE) {
        // It was a dotted quad number, so save result
        dest.sin_addr.s_addr = addr;
        dest.sin_family = AF_INET;
    }
    else {
        // Not in dotted quad form, so try and look it up
        hostent* hp = gethostbyname(host);
        if (hp != 0) {
            // Found an address for that host, so save it
            memcpy(&(dest.sin_addr), hp->h_addr, hp->h_length);
            dest.sin_family = hp->h_addrtype;
        }
        else {
            // Not a recognized hostname either!
            cerr << "Failed to resolve " << host << endl;
            return -1;
        }
    }

    return 0;
}

使用道具 举报

回复
论坛徽章:
456
ITPUB年度最佳版主
日期:2011-12-28 15:24:18马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14ITPUB年度最佳版主
日期:2014-02-19 10:05:27优秀写手
日期:2013-12-18 09:29:09ITPUB社区千里马徽章
日期:2013-06-09 10:15:34ITPUB年度最佳版主
日期:2013-01-30 17:30:25版主9段
日期:2012-07-03 02:21:03
12#
 楼主| 发表于 2006-7-19 17:25 | 只看该作者
//初试化ICMP的包头, 给data部分填充数据, 最后计算整个包的校验和

void init_ping_packet(ICMPHeader* icmp_hdr, int packet_size, int seq_no)
{
    // Set up the packet's fields
    icmp_hdr->type = ICMP_ECHO_REQUEST;
    icmp_hdr->code = 0;
    icmp_hdr->checksum = 0;
    icmp_hdr->id = (USHORT)GetCurrentProcessId();
    icmp_hdr->seq = seq_no;
    icmp_hdr->timestamp = GetTickCount();

    // "You're dead meat now, packet!"
    const unsigned long int deadmeat = 0xDEADBEEF;
    char* datapart = (char*)icmp_hdr + sizeof(ICMPHeader);
    int bytes_left = packet_size - sizeof(ICMPHeader);
    while (bytes_left > 0) {
        memcpy(datapart, &deadmeat, min(int(sizeof(deadmeat)),
                bytes_left));
        bytes_left -= sizeof(deadmeat);
        datapart += sizeof(deadmeat);
    }

    // Calculate a checksum on the result
    icmp_hdr->checksum = ip_checksum((USHORT*)icmp_hdr, packet_size);
}

// 发送生成的ICMP包
// 返回值 <0 表失败

int send_ping(SOCKET sd, const sockaddr_in& dest, ICMPHeader* send_buf,
        int packet_size)
{
    // Send the ping packet in send_buf as-is
    cout << "Sending " << packet_size << " bytes to " <<
            inet_ntoa(dest.sin_addr) << "..." << flush;
    int bwrote = sendto(sd, (char*)send_buf, packet_size, 0,
            (sockaddr*)&dest, sizeof(dest));
    if (bwrote == SOCKET_ERROR) {
        cerr << "send failed: " << WSAGetLastError() << endl;
        return -1;
    }
    else if (bwrote < packet_size) {
        cout << "sent " << bwrote << " bytes..." << flush;
    }

    return 0;
}


// 接受ICMP包
// 返回值 <0 表失败
int recv_ping(SOCKET sd, sockaddr_in& source, IPHeader* recv_buf,
        int packet_size)
{
    // Wait for the ping reply
    int fromlen = sizeof(source);
    int bread = recvfrom(sd, (char*)recv_buf,
            packet_size + sizeof(IPHeader), 0,
            (sockaddr*)&source, &fromlen);
    if (bread == SOCKET_ERROR) {
        cerr << "read failed: ";
        if (WSAGetLastError() == WSAEMSGSIZE) {
            cerr << "buffer too small" << endl;
        }
        else {
            cerr << "error #" << WSAGetLastError() << endl;
        }
        return -1;
    }

    return 0;
}

使用道具 举报

回复
论坛徽章:
456
ITPUB年度最佳版主
日期:2011-12-28 15:24:18马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14ITPUB年度最佳版主
日期:2014-02-19 10:05:27优秀写手
日期:2013-12-18 09:29:09ITPUB社区千里马徽章
日期:2013-06-09 10:15:34ITPUB年度最佳版主
日期:2013-01-30 17:30:25版主9段
日期:2012-07-03 02:21:03
13#
 楼主| 发表于 2006-7-19 17:25 | 只看该作者
// 对收到的ICMP解码
// 返回值 -2表忽略, -1 表失败, 0 成功
int decode_reply(IPHeader* reply, int bytes, sockaddr_in* from)
{
    // 跳过IP包头, 找到ICMP的包头
    unsigned short header_len = reply->h_len * 4;
    ICMPHeader* icmphdr = (ICMPHeader*)((char*)reply + header_len);

    // 包的长度合法, header_len + ICMP_MIN为最小ICMP包的长度
    if (bytes < header_len + ICMP_MIN) {
        cerr << "too few bytes from " << inet_ntoa(from->sin_addr) <<
                endl;
        return -1;
    }
    // 下面的包类型详细参见我的第一部分 "透析ICMP协议(一): 协议原理"
    else if (icmphdr->type != ICMP_ECHO_REPLY) {  //非正常回复
        if (icmphdr->type != ICMP_TTL_EXPIRE) {   //ttl减为零
            if (icmphdr->type == ICMP_DEST_UNREACH) { //主机不可达
                cerr << "Destination unreachable" << endl;
            }
            else {   //非法的ICMP包类型
                cerr << "Unknown ICMP packet type " << int(icmphdr->type) <<
                        " received" << endl;
            }
            return -1;
        }
    }
    else if (icmphdr->id != (USHORT)GetCurrentProcessId()) {
//不是本进程发的包, 可能是同机的其它ping进程发的
        return -2;
    }

    // 指出包传递了多远
    // [bugfree]我认为作者这里有问题, 因为有些系统的ttl初值为128如winXP,
    // 有些为256如我的DNS服务器211.97.168.129, 作者假设为256有点武断,
    // 可以一起探讨这个问题, 回email:zhangliangsd@hotmail.com
    int nHops = int(256 - reply->ttl);
    if (nHops == 192) {
        // TTL came back 64, so ping was probably to a host on the
        // LAN -- call it a single hop.
        nHops = 1;
    }
    else if (nHops == 128) {
        // Probably localhost
        nHops = 0;
    }

使用道具 举报

回复
论坛徽章:
456
ITPUB年度最佳版主
日期:2011-12-28 15:24:18马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14ITPUB年度最佳版主
日期:2014-02-19 10:05:27优秀写手
日期:2013-12-18 09:29:09ITPUB社区千里马徽章
日期:2013-06-09 10:15:34ITPUB年度最佳版主
日期:2013-01-30 17:30:25版主9段
日期:2012-07-03 02:21:03
14#
 楼主| 发表于 2006-7-19 17:26 | 只看该作者
// 所有工作结束,打印信息
    cout << endl << bytes << " bytes from " <<
            inet_ntoa(from->sin_addr) << ", icmp_seq " <<
            icmphdr->seq << ", ";
    if (icmphdr->type == ICMP_TTL_EXPIRE) {
        cout << "TTL expired." << endl;
    }
    else {
        cout << nHops << " hop" << (nHops == 1 ? "" : "s";
        cout << ", time: " << (GetTickCount() - icmphdr->timestamp) <<
                " ms." << endl;
    }

    return 0;
}


总结和建议:
-----------
   bugfree建议其中的这些方面需要改进:
    1. 头文件iostream.h 改为 iostream, 后者是标准C++的头文件
       同时添加对std::cout 和 std::endl;的引用
       对于cerr 建议都改为std::cout(因为后者头文件不支持)
    2. 程序的发送和接受采用了同步的方式, 这使得如果出现网络问题recv_ping将陷入持续等待.
       这是我们不想看到的.
       这三种技术可以达到目的:
         - 使用多线程, 将ping封装进线程, 在主程序中对它的超时进行处理
         - 使用select()函数来实现
         - 使用windows的 WSAAsyncSelect()
       这里对这些方法不作具体讨论, 留给读者自已完成.

使用道具 举报

回复
论坛徽章:
456
ITPUB年度最佳版主
日期:2011-12-28 15:24:18马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14ITPUB年度最佳版主
日期:2014-02-19 10:05:27优秀写手
日期:2013-12-18 09:29:09ITPUB社区千里马徽章
日期:2013-06-09 10:15:34ITPUB年度最佳版主
日期:2013-01-30 17:30:25版主9段
日期:2012-07-03 02:21:03
15#
 楼主| 发表于 2006-7-19 17:26 | 只看该作者
原理简介:
--------
   通过前四节的介绍, 可能大家对ICMP的应用有了初步的了解. 不过开始本节之前我对ICMP协议再从宏观上做些介绍. 大家都知道ICMP是为于ISO的第三层---网络层。 既是它同IP协议为于同一层, 然而大家可能也只到,ICMP协议要用到IP协议, 所以有一些书上说ICMP位ISO的第四层, 那是错误的。 同样这样那些书上这样画的的例子也是错误的,我就发现某外资通讯公司的资料上有这样两种错误的画法
   --------------------------        
   | ICMP | TCP(SCTP)  |
   --------------------------
   |         IP                   |
   --------------------------
   
   ---------------------------
   |...        | TCP(SCTP)   |
   ---------------------------
   | ICMP |   IP                |
   ----------------------------

其实如上的画法是错误的, 正确地画法应为:
   ---------------------        
   |...   | TCP(SCTP)   |
   ---------------------
   | ICMP |                 |
   ----------                |
   |       IP                  |
   ---------------------

接下来,让我们来说明怎样实现追踪路由的功能, 大家通过我的第一节的阅读可能已经了解了超时报文的具体内容(参见透析ICMP协议(一):  协议原理), 它在如果网关在处理数据报时发现生存周期域(ttl)为零,此数据报必须抛弃。网关同时必须通过超时信息通知源主机。这是它的报文的具体结构:
    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Type(11)  |     Code(0/1) |          Checksum             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                             unused                            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      Internet Header + 64 bits of Original Data Datagram      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

使用道具 举报

回复
论坛徽章:
456
ITPUB年度最佳版主
日期:2011-12-28 15:24:18马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14ITPUB年度最佳版主
日期:2014-02-19 10:05:27优秀写手
日期:2013-12-18 09:29:09ITPUB社区千里马徽章
日期:2013-06-09 10:15:34ITPUB年度最佳版主
日期:2013-01-30 17:30:25版主9段
日期:2012-07-03 02:21:03
16#
 楼主| 发表于 2006-7-19 17:27 | 只看该作者
通过利用setsockopt()函数设置ICMP包的IP包头中的ttl字段便可以达到这种效果。 具体过程如下, 假设你的IP到达目标地址需要过n个路由器(n>1)。 则
1. 初始化第一个ICMP包,并设置IP包头中的TTL为1, 则得到第一个数据路由器发回的超时报文
2. 一般情况下:初始化第i(i<n)个ICMP包,并设置IP包头中的TTL为i, 则得到第一个数据路由器发回的超时报文

剩下的问题为如何确定超时ICMP报文的路由器IP地址得到它的机器名的信息。 这个问题可能很多读者都会求, 用gethostbyaddr()可以得到答案。

经过理论的论证后, 让我们看看如何实现。
   

具体实现:(具体如何初试化ICMP的数据包上节已有详细的介绍,这里只是补充路由追踪的代码)
--------
主要代码如下:

unsigned long ipback = 0; //超时报文的IP的初试值
unsigned long ms = 0; //超时值
struct hostent *hHost;
char m_address[256];

//直到找到目标主机, 或达到最大跳数(HOPS)
while (ipback != ipfinal){  
hHost = 0;


//对到目标主机中间的某个路由器发放ping的报文(ttl为1~N-1之间)
if (Ping(m_address,ttl,ipback,ms))
{
  sin.sin_family = AF_INET;
  sin.sin_addr.S_un.S_addr = ipback; // 由函数返回的IP地址
    // 查找主机名
  hHost = gethostbyaddr((char*)&sin.sin_addr, 4, PF_INET);
  //这里可以输出hHost的内容
}
ttl++;
if (ttl > MAX_HOPS)  //达到最大跳数
{
  break;
}
}

使用道具 举报

回复
论坛徽章:
456
ITPUB年度最佳版主
日期:2011-12-28 15:24:18马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14ITPUB年度最佳版主
日期:2014-02-19 10:05:27优秀写手
日期:2013-12-18 09:29:09ITPUB社区千里马徽章
日期:2013-06-09 10:15:34ITPUB年度最佳版主
日期:2013-01-30 17:30:25版主9段
日期:2012-07-03 02:21:03
17#
 楼主| 发表于 2006-7-19 17:27 | 只看该作者
==================
ping函数的代码
==================
int Ping(const char * host, int ttl, unsigned long& ipback, unsigned long& ms)
{
SOCKET sockRaw;
struct sockaddr_in dest,from;
struct hostent * hp;
int bread,datasize;
int fromlen = sizeof(from);
int timeout = 100;
char *dest_ip;
char *icmp_data;
char *recvbuf;
unsigned int addr=0;
const int MAX_PACKET = 1024;

//初始化Socket
sockRaw = WSASocket (AF_INET,
      SOCK_RAW,
      IPPROTO_ICMP,
      NULL, 0, WSA_FLAG_OVERLAPPED);

if (sockRaw == INVALID_SOCKET)
{
  // 错误
}

   // 设置IP包头的ttl字段
bread = setsockopt(sockRaw, IPPROTO_IP, IP_TTL, (char *)&ttl, sizeof(int));
if(bread == SOCKET_ERROR)
{
  // 错误
}

// 设置接受超时为100ms
bread = setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));
if(bread == SOCKET_ERROR)
{
  // 错误
}

//禁止用Nagle算法缓存数据
bread = setsockopt(sockRaw, SOL_SOCKET, TCP_NODELAY, (const char*)&killnagle, sizeof(int));
if (bread == SOCKET_ERROR)
{
  // 错误

使用道具 举报

回复
论坛徽章:
456
ITPUB年度最佳版主
日期:2011-12-28 15:24:18马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14ITPUB年度最佳版主
日期:2014-02-19 10:05:27优秀写手
日期:2013-12-18 09:29:09ITPUB社区千里马徽章
日期:2013-06-09 10:15:34ITPUB年度最佳版主
日期:2013-01-30 17:30:25版主9段
日期:2012-07-03 02:21:03
18#
 楼主| 发表于 2006-7-19 17:28 | 只看该作者
timeout = 1000;
// 设置发送超时为100ms
bread = setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,
       sizeof(timeout));
if(bread == SOCKET_ERROR)
{
  // 错误
}

//下面的代码生成ICMP包
memset(&dest,0,sizeof(dest));
hp = gethostbyname(host);
if (!hp)
{
  addr = inet_addr(host);
}
if ((!hp)  && (addr == INADDR_NONE) )
{
  // 错误
}
if (hp != NULL)
  memcpy(&(dest.sin_addr),hp->h_addr,hp->h_length);
else
  dest.sin_addr.s_addr = addr;

//初始化dest
if (hp)
  dest.sin_family = hp->h_addrtype;
else
  dest.sin_family = AF_INET;

dest_ip = inet_ntoa(dest.sin_addr);

// 设置包长度
datasize = DEF_PACKET_SIZE;

// 计算包大小
datasize += sizeof(IcmpHeader);  

icmp_data = (char *)new[MAX_PACKET]; //分配内存,可以用new 和 delete
recvbuf = (char *)new[MAX_PACKET];

if (!icmp_data)
{
  // 释放内存,退出
}

if (!recvbuf)
{
  // 释放内存,退出 }
}

memset(icmp_data,0,MAX_PACKET);
fill_icmp_data(icmp_data,datasize); // 这个函数用来填充ICMP的数据包

int bwrote;
((IcmpHeader*)icmp_data)->i_cksum = 0;
((IcmpHeader*)icmp_data)->timestamp = GetTickCount(); // 存入当前时间值
((IcmpHeader*)icmp_data)->i_seq = seq_no++;

使用道具 举报

回复
论坛徽章:
456
ITPUB年度最佳版主
日期:2011-12-28 15:24:18马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14ITPUB年度最佳版主
日期:2014-02-19 10:05:27优秀写手
日期:2013-12-18 09:29:09ITPUB社区千里马徽章
日期:2013-06-09 10:15:34ITPUB年度最佳版主
日期:2013-01-30 17:30:25版主9段
日期:2012-07-03 02:21:03
19#
 楼主| 发表于 2006-7-19 17:28 | 只看该作者
// 计算校验和
((IcmpHeader*)icmp_data)->i_cksum = checksum((USHORT*)icmp_data, datasize);

  // 为了最后计算ICMP包回来的总时间
unsigned long tc = GetTickCount();
//发送数据包
bwrote = sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest, sizeof(dest));

if (bwrote == SOCKET_ERROR)
{
  // 错误
}
if (bwrote < datasize ) //发送字节数对否
{
}

// 接受数据包
bread = recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(struct sockaddr*)&from,
     &fromlen);
//计算总时间
ms = GetTickCount() - tc;

if (bread == SOCKET_ERROR)
{
  // 错误
}

// 得到返回的路由器
ipback = from.sin_addr.s_addr;

return 1;
}

===============================
函数fill_icmp_data()的源代码
===============================
//这个结构下面将用到
typedef struct _ihdr {
  BYTE i_type;
  BYTE i_code;
  USHORT i_cksum;
  USHORT i_id;
  USHORT i_seq;
  ULONG timestamp; /* 这不是ICMP包的一部分, 只是为了计算时间 */
}IcmpHeader;

使用道具 举报

回复
论坛徽章:
456
ITPUB年度最佳版主
日期:2011-12-28 15:24:18马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14ITPUB年度最佳版主
日期:2014-02-19 10:05:27优秀写手
日期:2013-12-18 09:29:09ITPUB社区千里马徽章
日期:2013-06-09 10:15:34ITPUB年度最佳版主
日期:2013-01-30 17:30:25版主9段
日期:2012-07-03 02:21:03
20#
 楼主| 发表于 2006-7-19 17:28 | 只看该作者
void fill_icmp_data(char * icmp_data, int datasize){

  IcmpHeader *icmp_hdr;
  char *datapart;

  icmp_hdr = (IcmpHeader*)icmp_data;  

  icmp_hdr->i_type = ICMP_ECHO;
  icmp_hdr->i_code = 0;
  icmp_hdr->i_id = (USHORT)GetCurrentProcessId();
  icmp_hdr->i_cksum = 0;
  icmp_hdr->i_seq = 0;
  
  datapart = icmp_data + sizeof(IcmpHeader);  //计算数据域的开始地址
  // 初试化数据域
  memset(datapart,'E', datasize - sizeof(IcmpHeader));

}

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表