2011-01-11 3 views
2

をしようとした後、私は常にデバイスのPing機能は、1020年には

にpingを実行する必要があるプログラムは、しかし、このピング機能は、1020年後にexactlly失敗してきた失敗したことは、私は二回のping機能を実行すると、それはで失敗

int ping(string target) 
{ 

int s, i, cc, packlen, datalen = DEFDATALEN; 
struct hostent *hp; 
struct sockaddr_in to, from; 
//struct protoent *proto; 
struct ip *ip; 
u_char *packet, outpack[MAXPACKET]; 
char hnamebuf[MAXHOSTNAMELEN]; 
string hostname; 
struct icmp *icp; 
int ret, fromlen, hlen; 
fd_set rfds; 
struct timeval tv; 
int retval; 
struct timeval start, end; 
int /*start_t, */end_t; 
bool cont = true; 

to.sin_family = AF_INET; 

// try to convert as dotted decimal address, else if that fails assume it's a hostname 
to.sin_addr.s_addr = inet_addr(target.c_str()); 
if (to.sin_addr.s_addr != (u_int)-1) 
    hostname = target; 
else 
{ 
    hp = gethostbyname(target.c_str()); 
    if (!hp) 
    { 
     cerr << "unknown host "<< target << endl; 
     return -1; 
    } 
    to.sin_family = hp->h_addrtype; 
    bcopy(hp->h_addr, (caddr_t)&to.sin_addr, hp->h_length); 
    strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1); 
    hostname = hnamebuf; 
} 
packlen = datalen + MAXIPLEN + MAXICMPLEN; 
if ((packet = (u_char *)malloc((u_int)packlen)) == NULL) 
{ 
    cerr << "malloc error\n"; 
    return -1; 
} 

/* 
if ((proto = getprotobyname("icmp")) == NULL) 
{ 
    cerr << "unknown protocol icmp" << endl; 
    return -1; 
} 
*/ 
if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) 
{ 
    perror("socket"); /* probably not running as superuser */ 
    return -1; 
} 

icp = (struct icmp *)outpack; 
icp->icmp_type = ICMP_ECHO; 
icp->icmp_code = 0; 
icp->icmp_cksum = 0; 
icp->icmp_seq = 12345; /* seq and id must be reflected */ 
icp->icmp_id = getpid(); 


cc = datalen + ICMP_MINLEN; 
icp->icmp_cksum = in_cksum((unsigned short *)icp,cc); 

gettimeofday(&start, NULL); 

i = sendto(s, (char *)outpack, cc, 0, (struct sockaddr*)&to, (socklen_t)sizeof(struct sockaddr_in)); 
if (i < 0 || i != cc) 
{ 
    if (i < 0) 
     perror("sendto error"); 
    cout << "wrote " << hostname << " " << cc << " chars, ret= " << i << endl; 
} 

// Watch stdin (fd 0) to see when it has input. 
FD_ZERO(&rfds); 
FD_SET(s, &rfds); 
// Wait up to one seconds. 
tv.tv_sec = 1; 
tv.tv_usec = 0; 

while(cont) 
{ 
    retval = select(s+1, &rfds, NULL, NULL, &tv); 
    if (retval == -1) 
    { 
     perror("select()"); 
     return -1; 
    } 
    else if (retval) 
    { 
     fromlen = sizeof(sockaddr_in); 
     if ((ret = recvfrom(s, (char *)packet, packlen, 0,(struct sockaddr *)&from, (socklen_t*)&fromlen)) < 0) 
     { 
      perror("recvfrom error"); 
      return -1; 
     } 

     // Check the IP header 
     ip = (struct ip *)((char*)packet); 
     hlen = sizeof(struct ip); 
     if (ret < (hlen + ICMP_MINLEN)) 
     { 
      cerr << "packet too short (" << ret << " bytes) from " << hostname << endl;; 
      return -1; 
     } 

     // Now the ICMP part 
     icp = (struct icmp *)(packet + hlen); 
     if (icp->icmp_type == ICMP_ECHOREPLY) 
     { 
      cout << "Recv: echo reply"<< endl; 
      if (icp->icmp_seq != 12345) 
      { 
       cout << "received sequence # " << icp->icmp_seq << endl; 
       continue; 
      } 
      if (icp->icmp_id != getpid()) 
      { 
       cout << "received id " << icp->icmp_id << endl; 
       continue; 
      } 
      cont = false; 
     } 
     else 
     { 
      cout << "Recv: not an echo reply" << endl; 
      continue; 
     } 

     gettimeofday(&end, NULL); 
     end_t = 1000000*(end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec); 

     if(end_t < 1) 
      end_t = 1; 

     cout << "Elapsed time = " << end_t << " usec" << endl; 
     return end_t; 
    } 
    else 
    { 
     cout << "No data within one seconds.\n"; 
     return 0; 
    } 
} 
return 0; 
} 

をしようとします正確に半分の510です。パターンは正確です。ここではネットワークプログラミングでかなり悪い1020マークの後に出力

socket: Too many open files 
ping returned -1 

Imがあるが、私は場合でも、上記のコードのために開始する知りません。

どこか近くに行方不明がありますか?

ピング機能がから取られる:http://www.linuxforums.org/forum/networking/60389-implementing-ping-c.html

編集:はい、あなたが終了する前にclose(s);でソケットをクローズする必要があるのUbuntu 10.10、Fedoraの13の同じ問題

おかげ

+1

オペレーティングシステムですでに利用可能な 'ping'ユーティリティを使用していないのはなぜですか?あなたが完全に理解していない、維持されていないコードよりも優れているでしょう。 –

+1

常にpingを実行する必要があるデバイスはどれですか?私はあなたがping floodを書くことを妨げるなら、あなたがネットワークプログラミングに悪いと思うのはとても幸せです。 「誰にでも1020回の試行で十分だ」 –

+0

@Cody Grey悪いネットワークプログラマーは、通常、あなたが意図していないときにping floodersを書くのに役立ちます。それは目的のものを書くのをやめさせるわけではありません。いずれにしても悪いです。 ;) –

答えて

5

を実行します関数。

+0

ちょっと良いニュースは、以前と比較してpingが遅くなるのでうまくいくようです。悪いニュースはあなたの答えを確認するために1020まで待っています。プラス1つ以下どれも –

+0

または:関数を2つの部分に分割します。 1つはソケットを開きます。もう1つはソケットにpingします。その後、一度だけ電話をかけてください。 –

4

リソースを割り当てるときは、を無料でにする必要があります。

巻き戻しが指摘された場合、閉じるソケットが必要です。

しかし、割り付けられたメモリ(malloc、40-ish)は、である必要があります。

bcopyの代わりにmemcpyを使用することを検討する必要があります。

+0

平均 'フリー(パケット)' –

+1

はい、mallocが成功すると後でそれを解放する必要があります。あなたが戻ってくるすべてのシングル(エラー)ケースで。 –

1

"unwind"と同意します。

プログラムではなく関数を実行することに注意してください。したがって、あなたのプロセスはまだ生きており、すべてのメモリ/リソースリークは自動的に解放されません。

closesocketのないsocket関数の呼び出しをコードに示している場合は、通常、目を傷つける必要があります。

+0

ahh私はいつもそれが 'socket'ではなく' connect'への呼び出しだと思っていました。私はそれに 'connect'という行を探していました –

関連する問題