2008-11-24 27 views
6

Tôi phải gọi ping từ mã C++. Tôi muốn dễ dàng đọc đầu ra để sử dụng thêm.Phương pháp tốt nhất để ping trong c + + trong linux là gì?

tôi đã đưa ra hai giải pháp:

  • sử dụng một ngã ba và một đường ống, chuyển hướng kết quả ping đến các đường ống và sau đó phân tích nó
  • tìm thấy một thư viện phù hợp với mục đích sử dụng một ping (ip_addresss) chức năng trực tiếp

Tôi muốn thứ hai nhưng tôi không tìm thấy bất cứ điều gì rõ ràng là một giải pháp tiêu chuẩn.

Bạn sẽ làm như thế nào?

Trả lời

3

Tôi sẽ sử dụng tùy chọn đầu tiên của bạn. Linux được xây dựng xung quanh khái niệm về việc có các ứng dụng nhỏ, chuyên dụng làm một điều thực sự tốt, giao tiếp với các đường ống. Ứng dụng của bạn không nên bao gồm thư viện để triển khai ping, vì đã có lệnh tích hợp để thực hiện, và nó hoạt động rất tốt!

+1

Có giải pháp đầu tiên có vẻ là cách tốt nhất. Cũng sử dụng giao thức ICMP yêu cầu quyền root. –

2

Kiểm tra BusyBox's source for 'ping' - bạn có thể sử dụng các chức năng ping4ping6. Chỉ cần lưu tâm đến GPL.

Sinh sản 'ping' cũng sẽ hoạt động - hãy kiểm tra popen(2) để có API đơn giản hơn cũng chạy trình bao. Nếu đó là vấn đề, pipe + fork + exec sẽ hoạt động.

+1

Cập nhật nguồn cho các chức năng ping có thể được tìm thấy ở đây (kể từ khi chúng chuyển sang Git): http://git.busybox.net/busybox/tree/networking/ping.c –

+0

@AlexMarshall tuyệt vời, cập nhật liên kết – orip

7

Từ quan điểm giáo dục của chế độ xem, gọi nhị phân bên ngoài là rất không thể phân bổ. Đặc biệt đối với một nhiệm vụ đơn giản như gửi một yêu cầu echo ICMP, bạn nên học một chút về socket.

+0

Tại sao? "Quan điểm giáo dục" là gì? – parsley72

0

tôi đã quản lý để làm như thế này:

tôi sử dụng popen mà về cơ bản tạo ra một đường ống, ngã ba và exec Sau đó, nếu tôi cần, tôi có thể chờ đợi với pclose.

5
#include <fcntl.h> 
#include <errno.h> 
#include <sys/socket.h> 
#include <resolv.h> 
#include <netdb.h> 
#include <netinet/in.h> 
#include <netinet/ip_icmp.h> 


#define PACKETSIZE 64 
struct packet 
{ 
    struct icmphdr hdr; 
    char msg[PACKETSIZE-sizeof(struct icmphdr)]; 
}; 

int pid=-1; 
struct protoent *proto=NULL; 
int cnt=1; 

/*--------------------------------------------------------------------*/ 
/*--- checksum - standard 1s complement checksum     ---*/ 
/*--------------------------------------------------------------------*/ 
unsigned short checksum(void *b, int len) 
{ 
    unsigned short *buf = b; 
    unsigned int sum=0; 
    unsigned short result; 

    for (sum = 0; len > 1; len -= 2) 
     sum += *buf++; 
    if (len == 1) 
     sum += *(unsigned char*)buf; 
    sum = (sum >> 16) + (sum & 0xFFFF); 
    sum += (sum >> 16); 
    result = ~sum; 
    return result; 
} 


/*--------------------------------------------------------------------*/ 
/*--- ping - Create message and send it.       ---*/ 
/* return 0 is ping Ok, return 1 is ping not OK.    ---*/ 
/*--------------------------------------------------------------------*/ 
int ping(char *adress) 
{ 
    const int val=255; 
    int i, sd; 
    struct packet pckt; 
    struct sockaddr_in r_addr; 
    int loop; 
    struct hostent *hname; 
    struct sockaddr_in addr_ping,*addr; 

    pid = getpid(); 
    proto = getprotobyname("ICMP"); 
    hname = gethostbyname(adress); 
    bzero(&addr_ping, sizeof(addr_ping)); 
    addr_ping.sin_family = hname->h_addrtype; 
    addr_ping.sin_port = 0; 
    addr_ping.sin_addr.s_addr = *(long*)hname->h_addr; 

    addr = &addr_ping; 

    sd = socket(PF_INET, SOCK_RAW, proto->p_proto); 
    if (sd < 0) 
    { 
     perror("socket"); 
     return 1; 
    } 
    if (setsockopt(sd, SOL_IP, IP_TTL, &val, sizeof(val)) != 0) 
    { 
     perror("Set TTL option"); 
     return 1; 
    } 
    if (fcntl(sd, F_SETFL, O_NONBLOCK) != 0) 
    { 
     perror("Request nonblocking I/O"); 
     return 1; 
    } 

    for (loop=0;loop < 10; loop++) 
    { 

     int len=sizeof(r_addr); 

     if (recvfrom(sd, &pckt, sizeof(pckt), 0, (struct sockaddr*)&r_addr, &len) > 0) 
     { 
      return 0; 
     } 

     bzero(&pckt, sizeof(pckt)); 
     pckt.hdr.type = ICMP_ECHO; 
     pckt.hdr.un.echo.id = pid; 
     for (i = 0; i < sizeof(pckt.msg)-1; i++) 
      pckt.msg[i] = i+'0'; 
     pckt.msg[i] = 0; 
     pckt.hdr.un.echo.sequence = cnt++; 
     pckt.hdr.checksum = checksum(&pckt, sizeof(pckt)); 
     if (sendto(sd, &pckt, sizeof(pckt), 0, (struct sockaddr*)addr, sizeof(*addr)) <= 0) 
      perror("sendto"); 

     usleep(300000); 

    } 

    return 1; 
} 

/*--------------------------------------------------------------------*/ 
/*--- main - look up host and start ping processes.    ---*/ 
/*--------------------------------------------------------------------*/ 
int main(int argc, char *argv[]) 
{ 

    if (ping("www.google.com")) 
     printf("Ping is not OK. \n"); 
    else 
     printf("Ping is OK. \n"); 


    return 0; 
} 
+0

Điều này chỉ hoạt động đối với người dùng root vì SOCK_RAW cần các đặc quyền mức root. Đọc ở đây về các loại socket: http://www.ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.progcomc/socket-types.htm – sb32134

Các vấn đề liên quan