Ping linux c++ сокеты
Есть реализация пингования (для проверки наличия соединения между клиентом и сервером), прочёл несколько статей, видел разные реализации, остановился на этой. В общем если пинг норм, возвращается 0, а если нет, то 1. У меня возвращается всегда 0, я пробовал разные хосты, реальные по типу google.com и локальный 127.0.0.1. Проверял при наличии соединения с сервером и без, результат один и тот же...Не понимаю, что я делаю не так..Если что, всё запускается корректно с правами root, так что не нужно удивляться, почему необработанный (сырой) сокет создаётся.
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/time.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <iostream>
#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 = (unsigned short*)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(const 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(AF_INET, SOCK_RAW, IPPROTO_ICMP); // пробовал с PF_INET, результат тот же
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++)
{
socklen_t 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;
}
int main() {
std::cout << ping("127.0.0.1") << std::endl;
getchar();
return 0;
}
Я проверил поле msg в пакете при чтении функцией recvfrom, оно не совпадает со значением при отправке..Но так всегда, что есть подключение к серверу, что нет...