亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 1706 | 回復(fù): 0
打印 上一主題 下一主題

[已解決] ping程序的問題. [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2010-11-17 19:58 |只看該作者 |倒序瀏覽
本帖最后由 PCliangtao 于 2010-11-17 20:50 編輯

在看UNP的時候,把書中的ping程序的例子的原理掌握之后,自己嘗試寫了一下.換湯不換藥... 只不過純粹只于IPv4打交道...
  不知道什么原理. 在發(fā)出echo的ICMP之后... 卻一直阻塞在recvmsg調(diào)用上... 我用tcpdump看...的確發(fā)生了ICMP ECHO...
  還有奇怪的一點的所... ping  www.hao123.com能夠正常工作... ping www.baidu.com www.goolge.com這樣的時候就一直阻塞在recvmsg上...
接觸網(wǎng)絡(luò)變成不久... 希望有經(jīng)驗的兄弟們給瞧瞧... 多謝..

NB: 仔細想了一下... 估計是發(fā)送的ICMP 包被遠端丟棄了...  仔細看了一下構(gòu)造ICMP 頭部的代碼... 汗ing... 校驗和的計算參數(shù)傳錯了...沒有把ICMP頭部算在內(nèi)...修改了一下...
       就好了...
       可是還有一點奇怪的是... ICMP 對回送請求的應(yīng)答應(yīng)該是在內(nèi)核里進行的吧...  但是為什么www.hao123.com主機能夠接受錯誤的校驗和的ICMP ECHO請求包呢?
       翻一翻TCP/IP的源代碼去...

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <signal.h>
  6. #include <errno.h>
  7. #include <netinet/in.h>
  8. #include <arpa/inet.h>
  9. #include <netinet/ip.h>
  10. #include <netinet/ip_icmp.h>
  11. #include <netdb.h>

  12. #define BUFSIZE 1024
  13. /* need those global vars, for simplicity */
  14. const char Usage[] = "Usage: ping [-v] host(hostname or hostIP)\n";
  15. static int nsnd;
  16. static int datalen;
  17. static int sockfd;
  18. static int verbose;
  19. static pid_t pid;
  20. static char sndbuf[BUFSIZE];
  21. static struct sockaddr *rcvaddr;
  22. static struct sockaddr *sndaddr;
  23. static socklen_t addrlen;
  24. /* some of the function prototypes */
  25. static void send_echo_icmp(void);
  26. static void recv_echoreply_icmp(char *, int, struct timeval *);
  27. static void sig_alrm(int signo);
  28. static char *show_addr_ip(struct sockaddr *, socklen_t len);
  29. static inline u_int16_t ip_fast_csum(const void *, unsigned int);

  30. static inline void err_quit(const char *str)
  31. {
  32.         perror(str);
  33.         exit(-1);
  34. }
  35. static inline void err_sys(const char *str)
  36. {
  37.         perror(str);
  38. }

  39. int main(int argc, char *argv[])
  40. {

  41.         int c;
  42.         char *host;
  43.         char *hostip;
  44.         char rcvbuf[BUFSIZE], ctlbuf[BUFSIZE];
  45.         struct msghdr msg;
  46.         struct iovec iov;
  47.         struct timeval rcvtv;
  48.         int size, n;
  49.         struct addrinfo *ai, *saved_ai, hint;
  50.        
  51.         while((c = getopt(argc, argv, "v")) != -1) {
  52.                 switch(c) {
  53.                 case 'v':
  54.                         verbose++;
  55.                         break;
  56.                 default:
  57.                         printf("unrecognized option %c\n", c);
  58.                         exit(-1);
  59.                 }
  60.         }
  61.         if(optind !=  argc - 1) {
  62.                 printf(Usage);
  63.                 exit(-1);
  64.         }
  65.         host = argv[optind];
  66.         datalen = 56;
  67.         signal(SIGALRM, sig_alrm);
  68.         pid = getpid() & 0xffff;
  69.         bzero(&hint, sizeof(hint));
  70.         hint.ai_flags = AI_CANONNAME;
  71.         hint.ai_family = AF_INET;
  72.         if(getaddrinfo(host, NULL, &hint, &ai) < 0)
  73.                 err_quit("getaddrinfo error: ");
  74.         saved_ai = ai;    /* don't need to do this actually */
  75.         for(; ai; ai = ai->ai_next)
  76.                 if(ai->ai_family == AF_INET)
  77.                         break;
  78.         if(!ai) {
  79.                 printf("cann't get IPv4 addrinfo\n");
  80.                 exit(-1);
  81.         }
  82.         hostip = show_addr_ip(ai->ai_addr, ai->ai_addrlen);
  83.         printf("ping %s (%s): %d data bytes\n", ai->ai_canonname ? \
  84.                 ai->ai_canonname : hostip, hostip, datalen);
  85.         sndaddr = ai->ai_addr;
  86.         addrlen = ai->ai_addrlen;
  87.         rcvaddr = (struct sockaddr *) malloc(addrlen);
  88.         if(!rcvaddr) {
  89.                 printf("malloc failed, OOM\n");
  90.                 exit(-1);
  91.         }

  92.         /* now we got all the information required, create the RAW socket and get started */
  93.         sockfd = socket(sndaddr->sa_family, SOCK_RAW, IPPROTO_ICMP);
  94.         if(sockfd < 0)
  95.                 err_quit("create socket error: ");
  96.         setuid(getuid()); /* only create RAW sock need privilege */

  97.         size = 60 * 1024;
  98.         setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
  99.         sig_alrm(SIGALRM);
  100.        
  101.         iov.iov_base = rcvbuf;
  102.         iov.iov_len = sizeof(rcvbuf);
  103.         msg.msg_name = rcvaddr;
  104.         msg.msg_namelen = addrlen;
  105.         msg.msg_iov = &iov;
  106.         msg.msg_iovlen = 1;
  107.         msg.msg_control = ctlbuf;
  108.         msg.msg_controllen = sizeof(ctlbuf);
  109.         while(1) {
  110.                 n = recvmsg(sockfd, &msg, 0);
  111.                 if(n < 0) {
  112.                         if(errno == EINTR)
  113.                                 continue;
  114.                         else {
  115.                                 err_sys("recvmsg error: ");
  116.                                 continue;
  117.                         }
  118.                 }
  119.                 gettimeofday(&rcvtv, NULL);
  120.         /*
  121.          * what if this process is slower than recv...maybe we'll get corrupted
  122.          * rcvtv .this should not be a problem, cause the internet is much much
  123.          * slower, respectly.
  124.          */
  125.                 recv_echoreply_icmp(rcvbuf, n, &rcvtv);
  126.         }
  127. }


  128. static void sig_alrm(int signo)
  129. {
  130.         send_echo_icmp();
  131.         alarm(1);
  132.         return;
  133. }


  134. /* send the icmp echo request */
  135. static void send_echo_icmp()
  136. {
  137.         int len;
  138.         struct icmp *icmp;
  139.         icmp = (struct icmp *)sndbuf;
  140.         /* build the icmp header */
  141.         icmp->icmp_type = ICMP_ECHO;
  142.         icmp->icmp_code = 0;
  143.         icmp->icmp_id = pid;
  144.         icmp->icmp_seq = ++nsnd;
  145.         if(datalen & 3) {
  146.                 fprintf(stderr, "datalen must be a multiple of 4!\n");
  147.                 datalen = (datalen + 3) & (~3UL);
  148.         }
  149.         memset(icmp->icmp_data, 0xa5, datalen);
  150.         gettimeofday((struct timeval *)icmp->icmp_data, NULL);
  151.         len = 8 + datalen;
  152.         icmp->icmp_cksum = 0;
  153.         icmp->icmp_cksum = ip_fast_csum(icmp->icmp_data, len >> 2);
  154.         if(sendto(sockfd, sndbuf, len, 0, sndaddr, addrlen) < 0)
  155.                 if(errno != EINTR)
  156.                         err_quit("sendto error: ");
  157. }

  158. static inline void cal_rtt(struct timeval *rcv, struct timeval *snd, double *rtt)
  159. {
  160.         if((rcv->tv_usec -= snd->tv_usec) < 0) {
  161.                 rcv->tv_sec--;
  162.                 rcv->tv_usec += 1000000;
  163.         }
  164.         rcv->tv_sec -= snd->tv_sec;
  165.         *rtt = rcv->tv_sec * 1000.0+ rcv->tv_usec / 1000.0;
  166. }

  167. static void recv_echoreply_icmp(char *rcvbuf, int len, struct timeval *rcv_tv)
  168. {
  169.         int iplen, icmplen;
  170.         double rtt;
  171.         struct ip *ip;
  172.         struct icmp *icmp;
  173.         struct timeval *snd_tv;
  174.         ip = (struct ip *)rcvbuf;
  175.         iplen = ip->ip_hl << 2;
  176.         if(ip->ip_p != IPPROTO_ICMP)
  177.                 goto ignore;
  178.         icmp = (struct icmp *)(rcvbuf + iplen);
  179.         icmplen = len - iplen;
  180.         if(icmplen < 8)
  181.                 goto ignore;
  182.         if(icmp->icmp_type == ICMP_ECHOREPLY) {
  183.                 if(icmp->icmp_id != pid)
  184.                         goto ignore;
  185.                 if(icmplen < 8+sizeof(struct timeval))
  186.                         goto ignore;
  187.                 snd_tv = (struct timeval *)icmp->icmp_data;
  188.                 cal_rtt(rcv_tv, snd_tv, &rtt);

  189.                 printf("%d bytes from %s: seq=%d, ttl=%d, rtt=%.3f ms\n", \
  190.                 icmplen, show_addr_ip(rcvaddr, addrlen), icmp->icmp_seq, \
  191.                         ip->ip_ttl, rtt);
  192.         } else if(verbose) {
  193.                 printf("%d bytes from %s: type=%d, code=%d\n", icmplen, \
  194.                 show_addr_ip(rcvaddr, addrlen), icmp->icmp_type,\
  195.                  icmp->icmp_code);
  196.         }
  197. ignore:
  198.         return;       
  199. }

  200. /* it's not safe, though */
  201. static char *show_addr_ip(struct sockaddr *sa, socklen_t len)
  202. {
  203.         static char ipbuf[INET6_ADDRSTRLEN];
  204.         switch(sa->sa_family) {
  205.         case AF_INET: {
  206.                 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
  207.                 if(len < sizeof(struct sockaddr_in))
  208.                         return NULL;
  209.                 if(inet_ntop(AF_INET, &sin->sin_addr, ipbuf,\
  210.                                                  INET6_ADDRSTRLEN) < 0)
  211.                         return NULL;
  212.                 return ipbuf;
  213.                 break;
  214.                 }
  215.         default:
  216.                 printf("don't support other addr type\n");
  217.                 return NULL;
  218.         }
  219. }

  220. /*
  221. *        This is a version of ip_compute_csum() optimized for IP headers,
  222. *        which always checksum on 4 octet boundaries.
  223. *
  224. *        By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
  225. *        Arnt Gulbrandsen.
  226. */
  227. static inline u_int16_t ip_fast_csum(const void *iph, unsigned int ihl)
  228. {
  229.         unsigned int sum;

  230.         asm volatile("movl (%1), %0        ;\n"
  231.                      "subl $4, %2        ;\n"
  232.                      "jbe 2f                ;\n"
  233.                      "addl 4(%1), %0        ;\n"
  234.                      "adcl 8(%1), %0        ;\n"
  235.                      "adcl 12(%1), %0;\n"
  236.                      "1:        adcl 16(%1), %0        ;\n"
  237.                      "lea 4(%1), %1        ;\n"
  238.                      "decl %2        ;\n"
  239.                      "jne 1b                ;\n"
  240.                      "adcl $0, %0        ;\n"
  241.                      "movl %0, %2        ;\n"
  242.                      "shrl $16, %0        ;\n"
  243.                      "addw %w2, %w0        ;\n"
  244.                      "adcl $0, %0        ;\n"
  245.                      "notl %0        ;\n"
  246.                      "2:                ;\n"
  247.         /* Since the input registers which are loaded with iph and ihl
  248.            are modified, we must also specify them as outputs, or gcc
  249.            will assume they contain their original values. */
  250.                      : "=r" (sum), "=r" (iph), "=r" (ihl)
  251.                      : "1" (iph), "2" (ihl)
  252.                      : "memory");
  253.         return (u_int16_t)sum;
  254. }
復(fù)制代碼
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP