久久久国产精品秘人口麻豆|永久免费AV无语国产|人成电影免费中文字幕|久久AV嫩草影院2

    1. <dfn id="yitbn"><samp id="yitbn"><progress id="yitbn"></progress></samp></dfn>

          <div id="yitbn"></div>

          1. 查看全部128種考試
            軟件水平考試
             考試動態(tài) 報考指南 歷年真題 模擬試題 復(fù)習資料 心得技巧 專業(yè)英語 技術(shù)文章 軟考論壇 考試用書
             程序員 軟件設(shè)計師 網(wǎng)絡(luò)管理員 網(wǎng)絡(luò)工程師 系統(tǒng)分析師 數(shù)據(jù)庫系統(tǒng)工程師
            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            ak47  
            【字體: ping命令工作原理詳細解析
            ping命令工作原理詳細解析
            spks.eeeigo.com 來源:考試吧eeeigo.com) 更新:2005-3-25 8:26:00 軟件水平考試 考試論壇

                ping的原理就是首先建立通道,然后發(fā)送包,對方接受后返回信息,這個包至少包括以下內(nèi)容,發(fā)送的時候,包的內(nèi)容包括對方的ip地址和自己的地址,還有序列數(shù),回送的時候包括雙方地址,還有時間等,主要是接受方在都是在操作系統(tǒng)內(nèi)核里做好的,時刻在監(jiān)聽,提供一段c程序的代碼,希望對大家有用。

            #include
            #include
            #include
            #include
            #include
            #include
            #include
            #include
            #include
            #include
            #include
            #include

            #define PACKET_SIZE 4096
            #define MAX_WAIT_TIME 5
            #define MAX_NO_PACKETS 3

            char sendpacket[PACKET_SIZE];
            char recvpacket[PACKET_SIZE];
            int sockfd,datalen=56;
            int nsend=0,nreceived=0;
            struct sockaddr_in dest_addr;
            pid_t pid;
            struct sockaddr_in from;
            struct timeval tvrecv;

            void statistics(int signo);
            unsigned short cal_chksum(unsigned short *addr,int len);
            int pack(int pack_no);
            void send_packet(void);
            void recv_packet(void);
            int unpack(char *buf,int len);
            void tv_sub(struct timeval *out,struct timeval *in);

            void statistics(int signo)
            { printf("\n--------------------PING statistics-------------------\n");
            printf("%d packets transmitted, %d received , %%%d lost\n",nsend,nreceived,
            (nsend-nreceived)/nsend*100);
            close(sockfd);
            exit(1);
            }

            /*校驗和算法*/
            unsigned short cal_chksum(unsigned short *addr,int len)
            { int nleft=len;
            int sum=0;
            unsigned short *w=addr;
            unsigned short answer=0;

            /*把ICMP報頭二進制數(shù)據(jù)以2字節(jié)為單位累加起來*/
            while(nleft>1)
            { sum+=*w++;
            nleft-=2;
            }

            /*若ICMP報頭為奇數(shù)個字節(jié),會剩下最后一字節(jié)。把最后一個字節(jié)視為一個2字節(jié)數(shù)據(jù)的高字節(jié),這個2字節(jié)數(shù)據(jù)的低字節(jié)為0,繼續(xù)累加*/
            if( nleft==1)
            { *(unsigned char *)(&answer)=*(unsigned char *)w;
            sum+=answer;
            }
            sum=(sum>>16)+(sum&0xffff);
            sum+=(sum>>16);
            answer=~sum;
            return answer;
            }

            /*設(shè)置ICMP報頭*/
            int pack(int pack_no)
            { int i,packsize;
            struct icmp *icmp;
            struct timeval *tval;

            icmp=(struct icmp*)sendpacket;
            icmp->icmp_type=ICMP_ECHO;
            icmp->icmp_code=0;
            icmp->icmp_cksum=0;
            icmp->icmp_seq=pack_no;
            icmp->icmp_id=pid;
            packsize=8+datalen;
            tval= (struct timeval *)icmp->icmp_data;
            gettimeofday(tval,NULL); /*記錄發(fā)送時間*/
            icmp->icmp_cksum=cal_chksum( (unsigned short *)icmp,packsize); /*校驗算法*/
            return packsize;
            }

            /*發(fā)送三個ICMP報文*/
            void send_packet()
            { int packetsize;
            while( nsend{ nsend++;
            packetsize=pack(nsend); /*設(shè)置ICMP報頭*/
            if( sendto(sockfd,sendpacket,packetsize,0,
            (struct sockaddr *)&dest_addr,sizeof(dest_addr) )<0 )
            { perror("sendto error");
            continue;
            }
            sleep(1); /*每隔一秒發(fā)送一個ICMP報文*/
            }
            }

            /*接收所有ICMP報文*/
            void recv_packet()
            { int n,fromlen;
            extern int errno;

            signal(SIGALRM,statistics);
            fromlen=sizeof(from);
            while( nreceived{ alarm(MAX_WAIT_TIME);
            if( (n=recvfrom(sockfd,recvpacket,sizeof(recvpacket),0,
            (struct sockaddr *)&from,&fromlen)) <0)
            { if(errno==EINTR)continue;
            perror("recvfrom error");
            continue;
            }
            gettimeofday(&tvrecv,NULL); /*記錄接收時間*/
            if(unpack(recvpacket,n)==-1)continue;
            nreceived++;
            }
            }

            /*剝?nèi)CMP報頭*/
            int unpack(char *buf,int len)
            { int i,iphdrlen;
            struct ip *ip;
            struct icmp *icmp;
            struct timeval *tvsend;
            double rtt;

            ip=(struct ip *)buf;
            iphdrlen=ip->ip_hl<<2; /*求ip報頭長度,即ip報頭的長度標志乘4*/
            icmp=(struct icmp *)(buf+iphdrlen); /*越過ip報頭,指向ICMP報頭*/
            len-=iphdrlen; /*ICMP報頭及ICMP數(shù)據(jù)報的總長度*/
            if( len<8) /*小于ICMP報頭長度則不合理*/
            { printf("ICMP packets\'s length is less than 8\n");
            return -1;
            }

            /*確保所接收的是我所發(fā)的的ICMP的回應(yīng)*/
            if( (icmp->icmp_type==ICMP_ECHOREPLY) && (icmp->icmp_id==pid) )
            { tvsend=(struct timeval *)icmp->icmp_data;
            tv_sub(&tvrecv,tvsend); /*接收和發(fā)送的時間差*/
            rtt=tvrecv.tv_sec*1000+tvrecv.tv_usec/1000; /*以毫秒為單位計算rtt*/

            /*顯示相關(guān)信息*/
            printf("%d byte from %s: icmp_seq=%u ttl=%d rtt=%.3f ms\n",
            len,
            inet_ntoa(from.sin_addr),
            icmp->icmp_seq,
            ip->ip_ttl,
            rtt);
            }
            else return -1;
            }

            main(int argc,char *argv[])
            { struct hostent *host;
            struct protoent *protocol;
            unsigned long inaddr=0l;
            int waittime=MAX_WAIT_TIME;
            int size=50*1024;

            if(argc<2)
            { printf("usage:%s hostname/IP address\n",argv[0]);
            exit(1);
            }

            if( (protocol=getprotobyname("icmp") )==NULL)
            { perror("getprotobyname");
            exit(1);
            }

            /*生成使用ICMP的原始套接字,這種套接字只有root才能生成*/
            if( (sockfd=socket(AF_INET,SOCK_RAW,protocol->p_proto) )<0)
            { perror("socket error");
            exit(1);
            }

            /* 回收root權(quán)限,設(shè)置當前用戶權(quán)限*/
            setuid(getuid());

            /*擴大套接字接收緩沖區(qū)到50K這樣做主要為了減小接收緩沖區(qū)溢出的
            的可能性,若無意中ping一個廣播地址或多播地址,將會引來大量應(yīng)答*/
            setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&size,sizeof(size) );
            bzero(&dest_addr,sizeof(dest_addr));
            dest_addr.sin_family=AF_INET;

            /*判斷是主機名還是ip地址*/
            if( inaddr=inet_addr(argv[1])==INADDR_NONE)
            { if((host=gethostbyname(argv[1]) )==NULL) /*是主機名*/
            { perror("gethostbyname error");
            exit(1);
            }
            memcpy( (char *)&dest_addr.sin_addr,host->h_addr,host->h_length);
            }
            else /*是ip地址*/
            memcpy( (char *)&dest_addr,(char *)&inaddr,host->h_length);
            /*獲取main的進程id,用于設(shè)置ICMP的標志符*/
            pid=getpid();
            printf("PING %s(%s): %d bytes data in ICMP packets.\n",argv[1],
            inet_ntoa(dest_addr.sin_addr),datalen);
            send_packet(); /*發(fā)送所有ICMP報文*/
            recv_packet(); /*接收所有ICMP報文*/
            statistics(SIGALRM); /*進行統(tǒng)計*/
            return 0;
            }

            /*兩個timeval結(jié)構(gòu)相減*/
            void tv_sub(struct timeval *out,struct timeval *in)
            { if( (out->tv_usec-=in->tv_usec)<0)
            { --out->tv_sec;
            out->tv_usec+=1000000;
            }
            out->tv_sec-=in->tv_sec;
            }

            轉(zhuǎn)帖于:軟件水平考試_考試吧
            文章搜索  
            看了本文的網(wǎng)友還看了:
            網(wǎng)友評論
            昵 稱: *  評 分: 1分 2分 3分 4分 5分
            標題:   匿名發(fā)表    (共有條評論)查看全部評論>>
            版權(quán)聲明 -------------------------------------------------------------------------------------
              如果軟件水平考試網(wǎng)所轉(zhuǎn)載內(nèi)容不慎侵犯了您的權(quán)益,請與我們聯(lián)系,我們將會及時處理。如轉(zhuǎn)載本軟件水平考試網(wǎng)內(nèi)容,請注明出處。
            關(guān)于本站  網(wǎng)站聲明  廣告服務(wù)  聯(lián)系方式  付款方式  站內(nèi)導航  客服中心  友情鏈接  考試論壇  網(wǎng)站地圖
            Copyright © 2004-2008 考試吧軟件水平考試網(wǎng) All Rights Reserved    
            中國科學院研究生院權(quán)威支持(北京) 電 話:010-62168566 傳 真:010-62192699
            百度大聯(lián)盟黃金認證  十佳網(wǎng)絡(luò)教育機構(gòu)  經(jīng)營許可證號:京ICP060677