Я написал сетевой пинг-код ICMP на C, ниже мой код, он пытался пинговать тысячи IP-адресов, но через несколько дней общее количество открытых сокетов увеличилось до 35K. Где я должен освободить мою розетку, пожалуйста.
struct packet {
struct icmphdr hdr;
char msg[64 - sizeof(struct icmphdr)];
};
struct protoent *proto = NULL;
void ping(char *bindIp, char **ipArr, size_t ipCount) {
//bindIp is the Ip in my machine for sending ip
//ipArr is the destination Ips need to ping
//ipCount is the total destination ip number
const int val = 255;
int i, sd, cnt = 1;
struct sockaddr_in r_addr;
r_addr.sin_family = AF_INET;
r_addr.sin_addr.s_addr = inet_addr(bindIp);
r_addr.sin_port = 0;
sd = socket(PF_INET, SOCK_RAW, proto->p_proto);
bind(sd, (struct sockaddr *) &r_addr, sizeof(r_addr));
if (sd < 0) {
perror("socket,you might need root/admin to operate\n");
return;
}
if (setsockopt(sd, SOL_IP, IP_TTL, &val, sizeof(val)) != 0)
perror("Set TTL option");
if (fcntl(sd, F_SETFL, O_NONBLOCK) != 0)
perror("Request nonblocking I/O");
for (i = 0; i < ipCount; i++) {
struct packet pckt;
struct hostent *hname;
hname = gethostbyname(ipArr[i]);
struct sockaddr_in addr;
proto = getprotobyname("ICMP");
bzero(&addr, sizeof(addr));
addr.sin_port = 0;
addr.sin_family = hname->h_addrtype;
addr.sin_addr.s_addr = *(long*) hname->h_addr;
if(i%5==0){
usleep(1001);
if(i%50000==0){
printf("ping oversea--i=%d,ip=%s\n",i,ipArr[i]);
}
}
bzero(&pckt, sizeof(pckt));
pckt.hdr.type = ICMP_ECHO;
long currTs = current_timestamp();
char buffer[20];
sprintf(buffer,"_%lu", currTs);
char *payload=concat(sendIp,buffer);
strcpy(pckt.msg,payload);
pckt.hdr.un.echo.id = 8899;
pckt.hdr.un.echo.sequence = cnt++;
pckt.hdr.checksum = checksum(&pckt, sizeof(pckt));
free(payload);
sendto(sd, &pckt, sizeof(pckt), 0, (struct sockaddr*) &addr,
sizeof(addr));
}
}