【gdb 看源码】【爱淘网站源码】【迷你魔域源码】windows ping源码

1.windows和linux下ping命令使用的不同之处
2.用vb编写一个调用ping.exe程序。
3.c语言ping程序中文注释
4.ping命令全链路分析(2)

windows ping源码

windows和linux下ping命令使用的不同之处

       1.Windows下默认发送四次数据包,完了之后自己结束,Linux下的ping程序默认不停发送数据包,直到你手动停止.

       2.ping命令程序不同,实现ping功能所使用 的源码不同.

       3.返回数据格式不同:

       Linux:ping [-dfnqrRv][-c<完成次数>][-i<间隔秒数>][-I<网络界面>][-l<前置载入>][-p<范本样式>][-s<数据包大小>][-t<存活数值>][主机名称或IP地址]

       Windows:

       Usage: ping [-t] [-a] [-n count] [-l size] [-f] [-i TTL] [-v TOS]

        [-r count] [-s count] [[-j host-list] | [-k host-list]]

        [-w timeout] target_name

       Options:

        -t Ping the specified host until stopped.

        To see statistics and continue - type Control-Break;

        To stop - type Control-C.

        -a Resolve addresses to hostnames.

        -n count Number of echo requests to send.

        -l size Send buffer size.

        -f Set Don't Fragment flag in packet.

        -i TTL Time To Live.

        -v TOS Type Of Service.

        -r count Record route for count hops.

        -s count Timestamp for count hops.

        -j host-list Loose source route along host-list.

        -k host-list Strict source route along host-list.

        -w timeout Timeout in milliseconds to wait for each reply.

用vb编写一个调用ping.exe程序。

       '改良了下

       '原来4秒刷一次,现在0.3秒刷一次

       '现在只返回毫秒了

       '你是不是为了玩山口山啊?

       '2个TextBox :

        Text1 - 输入ip

        Text2 - 显示结果

       '1个Timer : Timer1

       '1个CommandButton : Command1

       Option Explicit

       Private Const NORMAL_PRIORITY_CLASS = &H&

       Private Const STARTF_USESTDHANDLES = &H&

       Private Const STARTF_USESHOWWINDOW = &H1

       Private Type SECURITY_ATTRIBUTES

       nLength As Long

       lpSecurityDescriptor As Long

       bInheritHandle As Long

       End Type

       Private Type STARTUPINFO

       cb As Long

       lpReserved As Long

       lpDesktop As Long

       lpTitle As Long

       dwX As Long

       dwY As Long

       dwXSize As Long

       dwYSize As Long

       dwXCountChars As Long

       dwYCountChars As Long

       dwFillAttribute As Long

       dwFlags As Long

       wShowWindow As Integer

       cbReserved2 As Integer

       lpReserved2 As Long

       hStdInput As Long

       hStdOutput As Long

       hStdError As Long

       End Type

       Private Type PROCESS_INFORMATION

       hProcess As Long

       hThread As Long

       dwProcessID As Long

       dwThreadID As Long

       End Type

       Const SWP_NOMOVE = &H2

       Const SWP_NOSIZE = &H1

       Const FLAG = SWP_NOMOVE Or SWP_NOSIZE

       Const HWND_TOPMOST = -1

       Const HWND_NOTOPMOST = -2

       Const HWND_TOP = 0

       Const HWND_BOTTOM = 1

       Dim Proc As PROCESS_INFORMATION '进程信息

       Dim Start As STARTUPINFO '启动信息

       Dim SecAttr As SECURITY_ATTRIBUTES '安全属性

       Dim hReadPipe As Long '读取管道句柄

       Dim hWritePipe As Long '写入管道句柄

       Dim lngBytesRead As Long '读出数据的字节数

       Dim strBuffer As String * '读取管道的字符串buffer

       Dim Command As String 'DOS命令

       Dim ret As Long 'API函数返回值

       Private Declare Function SetWindowPos Lib "user" _

       (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, _

       ByVal y As Long, ByVal cx As Long, ByVal cy As Long, _

       ByVal wFlags As Long) As Long

       Private Declare Function CreatePipe Lib "kernel" (phReadPipe As Long, phWritePipe As Long, lpPipeAttributes As SECURITY_ATTRIBUTES, ByVal nSize As Long) As Long

       Private Declare Function CreateProcess Lib "kernel" Alias "CreateProcessA" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, lpProcessAttributes As SECURITY_ATTRIBUTES, lpThreadAttributes As SECURITY_ATTRIBUTES, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, lpEnvironment As Any, ByVal lpCurrentDriectory As String, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long

       Private Declare Function ReadFile Lib "kernel" (ByVal hFile As Long, ByVal lpBuffer As String, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Long) As Long

       Private Declare Function CloseHandle Lib "kernel" (ByVal hObject As Long) As Long

       Private Sub Command1_Click()

       If Not InitPipe Then

        Exit Sub

       Else

        'init

        Dim s As String

        s = ReadPipe

        'Me.Text2.Text = s

        Me.Timer1.Enabled = True

       End If

       End Sub

       Private Sub Form_Load()

       Call SetWindowPos(Me.hwnd, HWND_TOPMOST, 0, 0, 0, 0, FLAG)

       Me.Command1.Caption = "Start"

       Me.Timer1.Enabled = False

       Me.Timer1.Interval =

       Me.Text1.Text = "..."

       End Sub

       Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)

       ClosePipe

       End Sub

       Private Sub Timer1_Timer()

       Dim strPipe As String

       On Error Resume Next

       strPipe = ReadPipe()

       If Len(strPipe) > 0 Then

       If InStr(1, strPipe, "time") > 0 Then

       Dim lPosStart As Long

       Dim lPosEnd As Long

       Dim sMS As String

       lPosStart = InStr(strPipe, "time=")

       lPosEnd = InStr(strPipe, "ms")

       sMS = Mid(strPipe, lPosStart + 5, lPosEnd - lPosStart - 5)

       'Text2.Text = Now & "==============>" & vbCrLf & strPipe & vbCrLf & Text2.Text

       Text2.Text = sMS & vbCrLf & Text2.Text

       End If

       End If

       End Sub

       Private Function InitPipe() As Boolean

       '设置安全属性

       With SecAttr

       .nLength = LenB(SecAttr)

       .bInheritHandle = True

       .lpSecurityDescriptor = 0

       End With

       '创建管道

       ret = CreatePipe(hReadPipe, hWritePipe, SecAttr, 0)

       If ret = 0 Then

       MsgBox "无法创建管道", vbExclamation, "错误"

       GoTo ErrHdr

       End If

       '设置进程启动前的信息

       With Start

       .cb = LenB(Start)

       .dwFlags = STARTF_USESHOWWINDOW Or STARTF_USESTDHANDLES

       .hStdOutput = hWritePipe '设置输出管道

       .hStdError = hWritePipe '设置错误管道

       End With

       '启动进程

       Command = "c:\windows\system\ping.exe -t " & Me.Text1.Text 'DOS进程以ipconfig.exe为例

       ret = CreateProcess(vbNullString, Command, SecAttr, SecAttr, True, NORMAL_PRIORITY_CLASS, ByVal 0, vbNullString, Start, Proc)

       If ret = 0 Then

       MsgBox "无法启动新进程", vbExclamation, "错误"

       ret = CloseHandle(hWritePipe)

       ret = CloseHandle(hReadPipe)

       GoTo ErrHdr

       End If

       If False Then

       ErrHdr:

       InitPipe = False

       Exit Function

       End If

       InitPipe = True

       End Function

       Private Function ReadPipe() As String

       Dim lpOutputs As String

       '因为无需写入数据,所以先关闭写入管道。而且这里必须关闭此管道,否则将无法读取数据

       ret = CloseHandle(hWritePipe)

       '从输出管道读取数据,每次最多读取字节

       ret = ReadFile(hReadPipe, strBuffer, , lngBytesRead, ByVal 0)

       lpOutputs = lpOutputs & Left(strBuffer, lngBytesRead)

       ReadPipe = lpOutputs

       End Function

       Private Sub ClosePipe()

       On Error Resume Next

       '读取操作完成,关闭各句柄

       ret = CloseHandle(Proc.hProcess)

       ret = CloseHandle(Proc.hThread)

       ret = CloseHandle(hReadPipe)

       End Sub

c语言ping程序中文注释

       编写自己的一个ping程序,可以说是许多人迈出网络编程的第一步吧!!这个ping程序的源代码经过我的修改和调试,基本上可以取代windows中自带的ping程序. 各个模块后都有我的详细注释和修改日志,希望能够对大家的学习有所帮助!!

       /* 本程序的主要源代码来自MSDN网站, 笔者只是做了一些改进和注释! 另外需要注意的是在Build之前,必须加入ws2_.lib库文件,否则会提示"error LNK:"的错误!*/

       Version 1.1 修改记录:

        <1> 解决了socket阻塞的gdb 看源码问题,从而能够正确地处理超时的请求!

        <2> 增加了由用户控制发送ICMP包的数目的功能(即命令的第二个参数)

        <3> 增加了对ping结果的统计功能.

       #pragma pack(4)

       #include "winsock2.h"

       #include "stdlib.h"

       #include "stdio.h"

       #define ICMP_ECHO 8

       #define ICMP_ECHOREPLY 0

       #define ICMP_MIN 8 // minimum 8 byte icmp packet (just header)

       /* The IP header */

       typedef struct iphdr {

       unsigned int h_len:4; // length of the header

       unsigned int version:4; // Version of IP

       unsigned char tos; // Type of service

       unsigned short total_len; // total length of the packet

       unsigned short ident; // unique identifier

       unsigned short frag_and_flags; // flags

       unsigned char ttl;

       unsigned char proto; // protocol (TCP, UDP etc)

       unsigned short checksum; // IP checksum

       unsigned int sourceIP;

       unsigned int destIP;

       }IpHeader;

       //

       // ICMP header

       //

       typedef struct icmphdr {

       BYTE i_type;

       BYTE i_code; /* type sub code */

       USHORT i_cksum;

       USHORT i_id;

       USHORT i_seq;

       /* This is not the std header, but we reserve space for time */

       ULONG timestamp;

       }IcmpHeader;

       #define STATUS_FAILED 0xFFFF

       #define DEF_PACKET_SIZE

       #define DEF_PACKET_NUMBER 4 /* 发送数据报的个数 */

       #define MAX_PACKET

       #define xmalloc(s) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(s))

       #define xfree(p) HeapFree (GetProcessHeap(),0,(p))

       void fill_icmp_data(char *, int);

       USHORT checksum(USHORT *, int);

       int decode_resp(char *,int ,struct sockaddr_in *);

       void Usage(char *progname){

       fprintf(stderr,"Usage:\n");

       fprintf(stderr,"%s [number of packets] [data_size]\n",progname);

       fprintf(stderr,"datasize can be up to 1Kb\n");

       ExitProcess(STATUS_FAILED);

       }

       int main(int argc, char **argv){

       WSADATA wsaData;

       SOCKET sockRaw;

       struct sockaddr_in dest,from;

       struct hostent * hp;

       int bread,datasize,times;

       int fromlen = sizeof(from);

       int timeout = ;

       int statistic = 0; /* 用于统计结果 */

       char *dest_ip;

       char *icmp_data;

       char *recvbuf;

       unsigned int addr=0;

       USHORT seq_no = 0;

       if (WSAStartup(MAKEWORD(2,1),&wsaData) != 0){

       fprintf(stderr,"WSAStartup failed: %d\n",GetLastError());

       ExitProcess(STATUS_FAILED);

       }

       if (argc <2 ) {

       Usage(argv[0]);

       }

       sockRaw = WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL, 0,WSA_FLAG_OVERLAPPED);

       //

       //注:为了使用发送接收超时设置(即设置SO_RCVTIMEO, SO_SNDTIMEO),

       // 必须将标志位设为WSA_FLAG_OVERLAPPED !

       //

       if (sockRaw == INVALID_SOCKET) {

       fprintf(stderr,爱淘网站源码"WSASocket() failed: %d\n",WSAGetLastError());

       ExitProcess(STATUS_FAILED);

       }

       bread = setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,

       sizeof(timeout));

       if(bread == SOCKET_ERROR) {

       fprintf(stderr,"failed to set recv timeout: %d\n",WSAGetLastError());

       ExitProcess(STATUS_FAILED);

       }

       timeout = ;

       bread = setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,

       sizeof(timeout));

       if(bread == SOCKET_ERROR) {

       fprintf(stderr,"failed to set send timeout: %d\n",WSAGetLastError());

       ExitProcess(STATUS_FAILED);

       }

       memset(&dest,0,sizeof(dest));

       hp = gethostbyname(argv[1]);

       if (!hp){

       addr = inet_addr(argv[1]);

       }

       if ((!hp) && (addr == INADDR_NONE) ) {

       fprintf(stderr,"Unable to resolve %s\n",argv[1]);

       ExitProcess(STATUS_FAILED);

       }

       if (hp != NULL)

       memcpy(&(dest.sin_addr),hp->h_addr,hp->h_length);

       else

       dest.sin_addr.s_addr = addr;

       if (hp)

       dest.sin_family = hp->h_addrtype;

       else

       dest.sin_family = AF_INET;

       dest_ip = inet_ntoa(dest.sin_addr);

       //

       // atoi函数原型是: int atoi( const char *string );

       // The return value is 0 if the input cannot be converted to an integer !

       //

       if(argc>2)

       {

       times=atoi(argv[2]);

       if(times == 0)

        times=DEF_PACKET_NUMBER;

       }

       else

        times=DEF_PACKET_NUMBER;

       if (argc >3)

       {

       datasize = atoi(argv[3]);

        if (datasize == 0)

        datasize = DEF_PACKET_SIZE;

       if (datasize >) /* 用户给出的数据包大小太大 */

       {

        fprintf(stderr,"WARNING : data_size is too large !\n");

        datasize = DEF_PACKET_SIZE;

       }

       }

       else

        datasize = DEF_PACKET_SIZE;

       datasize += sizeof(IcmpHeader);

       icmp_data = (char*)xmalloc(MAX_PACKET);

       recvbuf = (char*)xmalloc(MAX_PACKET);

       if (!icmp_data) {

       fprintf(stderr,"HeapAlloc failed %d\n",GetLastError());

       ExitProcess(STATUS_FAILED);

       }

       memset(icmp_data,0,MAX_PACKET);

       fill_icmp_data(icmp_data,datasize);

       //

       //显示提示信息

       //

       fprintf(stdout,"\nPinging %s ....\n\n",dest_ip);

       for(int i=0;i{

       int bwrote;

       ((IcmpHeader*)icmp_data)->i_cksum = 0;

       ((IcmpHeader*)icmp_data)->timestamp = GetTickCount();

       ((IcmpHeader*)icmp_data)->i_seq = seq_no++;

       ((IcmpHeader*)icmp_data)->i_cksum = checksum((USHORT*)icmp_data,datasize);

       bwrote = sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest,sizeof(dest));

       if (bwrote == SOCKET_ERROR){

       if (WSAGetLastError() == WSAETIMEDOUT) {

       printf("Request timed out.\n");

       continue;

       }

       fprintf(stderr,"sendto failed: %d\n",WSAGetLastError());

       ExitProcess(STATUS_FAILED);

       }

       if (bwrote < datasize ) {

       fprintf(stdout,"Wrote %d bytes\n",bwrote);

       }

       bread = recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(struct sockaddr*)&from,&fromlen);

       if (bread == SOCKET_ERROR){

       if (WSAGetLastError() == WSAETIMEDOUT) {

       printf("Request timed out.\n");

       continue;

       }

       fprintf(stderr,"recvfrom failed: %d\n",WSAGetLastError());

       ExitProcess(STATUS_FAILED);

       }

       if(!decode_resp(recvbuf,bread,&from))

       statistic++; /* 成功接收的数目++ */

       Sleep();

       }

       /

*

       Display the statistic result

       */

       fprintf(stdout,"\nPing statistics for %s \n",dest_ip);

       fprintf(stdout," Packets: Sent = %d,Received = %d, Lost = %d (%2.0f%% loss)\n",times,

        statistic,(times-statistic),(float)(times-statistic)/times*);

       WSACleanup();

       return 0;

       }

       /*

       The response is an IP packet. We must decode the IP header to locate

       the ICMP data

       */

       int decode_resp(char *buf, int bytes,struct sockaddr_in *from) {

       IpHeader *iphdr;

       IcmpHeader *icmphdr;

       unsigned short iphdrlen;

       iphdr = (IpHeader *)buf;

       iphdrlen = (iphdr->h_len) * 4 ; // number of -bit words *4 = bytes

       if (bytes < iphdrlen + ICMP_MIN) {

       printf("Too few bytes from %s\n",inet_ntoa(from->sin_addr));

       }

       icmphdr = (IcmpHeader*)(buf + iphdrlen);

       if (icmphdr->i_type != ICMP_ECHOREPLY) {

       fprintf(stderr,"non-echo type %d recvd\n",icmphdr->i_type);

       return 1;

       }

       if (icmphdr->i_id != (USHORT)GetCurrentProcessId()) {

       fprintf(stderr,"someone else''s packet!\n");

       return 1;

       }

       printf("%d bytes from %s:",bytes, inet_ntoa(from->sin_addr));

       printf(" icmp_seq = %d. ",icmphdr->i_seq);

       printf(" time: %d ms ",GetTickCount()-icmphdr->timestamp);

       printf("\n");

       return 0;

       }

       USHORT checksum(USHORT *buffer, int size) {

       unsigned long cksum=0;

       while(size >1) {

       cksum+=*buffer++;

       size -=sizeof(USHORT);

       }

       if(size) {

       cksum += *(UCHAR*)buffer;

       }

       cksum = (cksum >> ) + (cksum & 0xffff);

       cksum += (cksum >>);

       return (USHORT)(~cksum);

       }

       /*

       Helper function to fill in various stuff in our ICMP request.

       */

       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);

       //

       // Place some junk in the buffer.

       //

       memset(datapart,''E'', datasize - sizeof(IcmpHeader));

       }

       /

更多内容请点击【娱乐】专栏