设为首页 加入收藏

TOP

ping命令的C语言实现(linux, IPv4,简单版)(二)
2014-11-23 23:18:08 来源: 作者: 【 】 浏览:3
Tags:ping 命令 语言 实现 linux IPv4 简单
msg.msg_name = g_proto.sarecv;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = controlbuf;
//开始死循环,不断读取和处理从服务器中返回的信息
while( 1 )
{
msg.msg_namelen = g_proto.salen;
msg.msg_controllen = sizeof(controlbuf);
n = recvmsg(g_sockfd, &msg, 0);
if (n < 0)
{
if (errno == EINTR)
continue;
else
error_quit("recvmsg error");
}
//分析返回内容,产生输出
gettimeofday(&tval, NULL);
proc_msg(recvbuf, n, &msg, &tval);
}
}
void proc_msg(char *ptr, ssize_t len, struct msghdr *msg, struct timeva l *tvrecv)
{
int hlen1, icmplen;
double rtt;
struct ip *ip;
struct icmp *icmp;
struct timeva l *tvsend;
//将服务器返回的字符串强转为ip结构
ip = (struct ip *) ptr;
//得到IP表头的长度
hlen1 = ip->ip_hl << 2;
//如果不是ICMP的应答,则返回
if (ip->ip_p != IPPROTO_ICMP)
return;
icmp = (struct icmp *) (ptr + hlen1);
//长度不足,不是合法应答
if ( (icmplen = len - hlen1) < 8)
return;
//不是回显应答,返回
if (icmp->icmp_type != ICMP_ECHOREPLY)
return;
//不是我们发出请求的应答,返回
if (icmp->icmp_id != g_pid)
return;
//长度不足,非法应答
if (icmplen < 16)
return;
//计算网络延时
tvsend = (struct timeva l *) icmp->icmp_data;
tv_sub(tvrecv, tvsend);
rtt = tvrecv->tv_sec * 1000.0 + tvrecv->tv_usec / 1000.0;
//输出信息
printf("%d bytes from %s: seq=%u, ttl=%d, rtt=%.3f ms\n",
icmplen, sock_ntop_host(g_proto.sarecv, g_proto.salen),
icmp->icmp_seq, ip->ip_ttl, rtt);
}
void send_msg(void)
{
int len;
int res;
struct icmp *icmp;
char sendbuf[BUFSIZE];
static int nsent = 0;
//根据ICMPv4协议来设置发送信息
icmp = (struct icmp *) sendbuf;
//ICMP回显请求
icmp->icmp_type = ICMP_ECHO;
icmp->icmp_code = 0;
//ICMP标识符字段为本进程的PID
icmp->icmp_id = g_pid;
//ICMP序列号字段为不断递增的全局变量nsent
icmp->icmp_seq = nsent++;
//ICMP数据字段为当前时间截,空白部分填充0xa5
memset(icmp->icmp_data, 0xa5, DATA_LEN);
gettimeofday((struct timeva l *)icmp->icmp_data, NULL);
//计算并填充校验和
len = 8 + DATA_LEN;
icmp->icmp_cksum = 0;
icmp->icmp_cksum = in_cksum((u_short *) icmp, len);
//发送数据
res = sendto(g_sockfd, sendbuf, len, 0, g_proto.sasend, g_proto.salen);
if( -1 == res )
error_quit("sendto error");
}
void sig_alrm(int signo)
{
send_msg();
alarm(1);
}
void tv_sub(struct timeva l *out, struct timeva l *in)
{
//将两个时间相减,并把结果存入第一个参数中( out -= in )
if ( (out->tv_usec -= in->tv_usec) < 0)
{
--out->tv_sec;
out->tv_usec += 1000000;
}
out->tv_sec -= in->tv_sec;
}
struct addrinfo *host_serv(const char *host, const char *serv, int family, int socktype)
{
int n;
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags = AI_CANONNAME;
hints.ai_family = family;
hints.ai_socktype = socktype;
n = getaddrinfo(host, serv, &hints, &res);
if ( n != 0 )
error_quit("getaddrinfo er
首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C语言中一些容易被人忽略的东西 .. 下一篇C语言中一些容易被人忽略的东西 ..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: