⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ping.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
    }

    IcmpSock = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, 0);
    if (IcmpSock == INVALID_SOCKET) {
        printf("Could not create socket (#%d).\n", WSAGetLastError());
        return FALSE;
    }

    ZeroMemory(&Target, sizeof(Target));
    phe = NULL;
    Addr = inet_addr(TargetName);
    if (Addr == INADDR_NONE) {
        phe = gethostbyname(TargetName);
        if (phe == NULL) {
            printf("Unknown host %s.\n", TargetName);
            return FALSE;
        }
    }

    if (phe != NULL) {
        CopyMemory(&Target.sin_addr, phe->h_addr, phe->h_length);
    } else {
        Target.sin_addr.s_addr = Addr;
    }

    if (phe != NULL) {
		Target.sin_family = phe->h_addrtype;
    } else {
        Target.sin_family = AF_INET;
    }

    TargetIP		= inet_ntoa(Target.sin_addr);
    CurrentSeqNum	= 0;
    SentCount		= 0;
	LostCount		= 0;
    MinRTT.QuadPart = 0;
    MaxRTT.QuadPart = 0;
    SumRTT.QuadPart = 0;
    MinRTTSet       = FALSE;
    return TRUE;
}

/* Close socket */
static VOID Cleanup(VOID)
{
    if (IcmpSock != INVALID_SOCKET)
        closesocket(IcmpSock);

    WSACleanup();
}

static VOID QueryTime(PLARGE_INTEGER Time)
{
    if (UsePerformanceCounter) {
        if (QueryPerformanceCounter(Time) == 0) {
            /* This should not happen, but we fall
               back to GetCurrentTick() if it does */
            Time->u.LowPart  = (ULONG)GetTickCount();
            Time->u.HighPart = 0;

            /* 1 tick per millisecond for GetCurrentTick() */
            TicksPerMs.QuadPart = 1;
            /* GetCurrentTick() cannot handle microseconds */
            TicksPerUs.QuadPart = 1;

            UsePerformanceCounter = FALSE;
        }
    } else {
        Time->u.LowPart  = (ULONG)GetTickCount();
        Time->u.HighPart = 0;
    }
}

static VOID TimeToMsString(LPSTR String, LARGE_INTEGER Time)
{
    CHAR          Convstr[40];
    LARGE_INTEGER LargeTime;

    LargeTime.QuadPart = Time.QuadPart / TicksPerMs.QuadPart;

    _i64toa(LargeTime.QuadPart, Convstr, 10);
	strcpy(String, Convstr);
    strcat(String, "ms");
}

/* Locate the ICMP data and print it. Returns TRUE if the packet was good,
   FALSE if not */
static BOOL DecodeResponse(PCHAR buffer, UINT size, PSOCKADDR_IN from)
{
    PIPv4_HEADER      IpHeader;
    PICMP_ECHO_PACKET Icmp;
  	UINT              IphLength;
    CHAR              Time[100];
    LARGE_INTEGER     RelativeTime;
    LARGE_INTEGER     LargeTime;
    CHAR              Sign[2];

    IpHeader = (PIPv4_HEADER)buffer;

    IphLength = IpHeader->IHL * 4;

    if (size  < IphLength + ICMP_MINSIZE) {
#ifdef DBG
        printf("Bad size (0x%X < 0x%X)\n", size, IphLength + ICMP_MINSIZE);
#endif /* DBG */
        return FALSE;
    }

    Icmp = (PICMP_ECHO_PACKET)(buffer + IphLength);

    if (Icmp->Icmp.Type != ICMPMSG_ECHOREPLY) {
#ifdef DBG
        printf("Bad ICMP type (0x%X should be 0x%X)\n", Icmp->Icmp.Type, ICMPMSG_ECHOREPLY);
#endif /* DBG */
        return FALSE;
    }

    if (Icmp->Icmp.Id != (USHORT)GetCurrentProcessId()) {
#ifdef DBG
        printf("Bad ICMP id (0x%X should be 0x%X)\n", Icmp->Icmp.Id, (USHORT)GetCurrentProcessId());
#endif /* DBG */
        return FALSE;
    }

    QueryTime(&LargeTime);

    RelativeTime.QuadPart = (LargeTime.QuadPart - Icmp->Timestamp.QuadPart);

    if ((RelativeTime.QuadPart / TicksPerMs.QuadPart) < 1) {
        strcpy(Sign, "<");
        strcpy(Time, "1ms");
    } else {
        strcpy(Sign, "=");
        TimeToMsString(Time, RelativeTime);
    }


    printf("Reply from %s: bytes=%d time%s%s TTL=%d\n", inet_ntoa(from->sin_addr),
      size - IphLength - sizeof(ICMP_ECHO_PACKET), Sign, Time, IpHeader->TTL);
    if (RelativeTime.QuadPart < MinRTT.QuadPart || !MinRTTSet) {
	    MinRTT.QuadPart = RelativeTime.QuadPart;
        MinRTTSet = TRUE;
    }
	if (RelativeTime.QuadPart > MaxRTT.QuadPart)
	    MaxRTT.QuadPart = RelativeTime.QuadPart;

    SumRTT.QuadPart += RelativeTime.QuadPart;

	return TRUE;
}

/* Send and receive one ping */
static BOOL Ping(VOID)
{
    INT                 Status;
    SOCKADDR            From;
    INT                 Length;
    PVOID               Buffer;
    UINT                Size;
    PICMP_ECHO_PACKET   Packet;

    /* Account for extra space for IP header when packet is received */
    Size   = DataSize + 128;
    Buffer = GlobalAlloc(0, Size);
    if (!Buffer) {
        printf("Not enough free resources available.\n");
        return FALSE;
    }

    ZeroMemory(Buffer, Size);
    Packet = (PICMP_ECHO_PACKET)Buffer;

    /* Assemble ICMP echo request packet */
    Packet->Icmp.Type     = ICMPMSG_ECHOREQUEST;
    Packet->Icmp.Code     = 0;
    Packet->Icmp.Id	      = (USHORT)GetCurrentProcessId();
    Packet->Icmp.SeqNum   = htons((USHORT)CurrentSeqNum);
    Packet->Icmp.Checksum = 0;

    /* Timestamp is part of data area */
    QueryTime(&Packet->Timestamp);

    CopyMemory(Buffer, &Packet->Icmp, sizeof(ICMP_ECHO_PACKET) + DataSize);
    /* Calculate checksum for ICMP header and data area */
    Packet->Icmp.Checksum = Checksum((PUSHORT)&Packet->Icmp, sizeof(ICMP_ECHO_PACKET) + DataSize);

    CurrentSeqNum++;

	/* Send ICMP echo request */

    FD_ZERO(&Fds);
    FD_SET(IcmpSock, &Fds);
    Timeval.tv_sec  = Timeout / 1000;
    Timeval.tv_usec = Timeout % 1000;
    Status = select(0, NULL, &Fds, NULL, &Timeval);
    if ((Status != SOCKET_ERROR) && (Status != 0)) {

#ifdef DBG
        printf("Sending packet\n");
        DisplayBuffer(Buffer, sizeof(ICMP_ECHO_PACKET) + DataSize);
        printf("\n");
#endif /* DBG */

        Status = sendto(IcmpSock, Buffer, sizeof(ICMP_ECHO_PACKET) + DataSize,
            0, (SOCKADDR*)&Target, sizeof(Target));
        SentCount++;
    }
    if (Status == SOCKET_ERROR) {
        if (WSAGetLastError() == WSAEHOSTUNREACH) {
            printf("Destination host unreachable.\n");
        } else {
            printf("Could not transmit data (%d).\n", WSAGetLastError());
        }
        GlobalFree(Buffer);
        return FALSE;
    }

    /* Expect to receive ICMP echo reply */
    FD_ZERO(&Fds);
    FD_SET(IcmpSock, &Fds);
    Timeval.tv_sec  = Timeout / 1000;
    Timeval.tv_usec = Timeout % 1000;

    Status = select(0, &Fds, NULL, NULL, &Timeval);
    if ((Status != SOCKET_ERROR) && (Status != 0)) {
        Length = sizeof(From);
        Status = recvfrom(IcmpSock, Buffer, Size, 0, &From, &Length);

#ifdef DBG
        printf("Received packet\n");
        DisplayBuffer(Buffer, Status);
        printf("\n");
#endif /* DBG */
    }
    if (Status == SOCKET_ERROR) {
        if (WSAGetLastError() != WSAETIMEDOUT) {
            printf("Could not receive data (%d).\n", WSAGetLastError());
            GlobalFree(Buffer);
            return FALSE;
        }
        Status = 0;
    }

    if (Status == 0) {
        printf("Request timed out.\n");
        LostCount++;
        GlobalFree(Buffer);
        return TRUE;
    }

    if (!DecodeResponse(Buffer, Status, (PSOCKADDR_IN)&From)) {
        /* FIXME: Wait again as it could be another ICMP message type */
        printf("Request timed out (incomplete datagram received).\n");
        LostCount++;
    }

    GlobalFree(Buffer);
    return TRUE;
}


/* Program entry point */
int main(int argc, char* argv[])
{
    UINT Count;
    CHAR MinTime[20];
    CHAR MaxTime[20];
    CHAR AvgTime[20];

    Reset();

    if ((ParseCmdline(argc, argv)) && (Setup())) {

        printf("\nPinging %s [%s] with %d bytes of data:\n\n",
            TargetName, TargetIP, DataSize);

		Count = 0;
		while ((NeverStop) || (Count < PingCount)) {
			Ping();
			Sleep(Timeout);
			Count++;
		};

        Cleanup();

		/* Calculate avarage round trip time */
        if ((SentCount - LostCount) > 0) {
            AvgRTT.QuadPart = SumRTT.QuadPart / (SentCount - LostCount);
        } else {
            AvgRTT.QuadPart = 0;
        }

        /* Calculate loss percent */
        Count = SentCount ? (LostCount * 100) / SentCount : 0;

        if (!MinRTTSet)
            MinRTT = MaxRTT;

        TimeToMsString(MinTime, MinRTT);
        TimeToMsString(MaxTime, MaxRTT);
        TimeToMsString(AvgTime, AvgRTT);

        /* Print statistics */
        printf("\nPing statistics for %s:\n", TargetIP);
        printf("    Packets: Sent = %d, Received = %d, Lost = %d (%d%% loss),\n",
            SentCount, SentCount - LostCount, LostCount, Count);
        printf("Approximate round trip times in milli-seconds:\n");
        printf("    Minimum = %s, Maximum = %s, Average = %s\n",
            MinTime, MaxTime, AvgTime);
    }
	return 0;
}

/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -