借鉴了《unix网络编程API》上面的关于traceroute的命令,目的是进一步理解sock_raw,本程序只适用于ipv4。
从这次编程中,学到了:
(1)注意=和== 的区别,对于有判断的还好点,有时候能直接看到,但是如果只是一个句子(如done=1和done==1),这和时候就不好找了,坑了我好几次啊。
(2)alarm(0)是用来取消原来的闹铃的
(3)《unix网络编程API》关于超时的设置是错的,因为signal(SIGALRM, sigz_alrm)中的signal函数,会自动重启(我用的ubuntu12.04,因为sigaction中的ai_flags选项中只有SA_RESTART), 即由于信号处理而中断的函数重新运行,而不会中断产生errno=EINT;
(4) socket选项中的SOCK_RAW必须是超级用户才能运行。
(5) 可以通过setsockopt(sendfd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)可以设置ttl
(6) 用sendfd(用于SOCK_DGRAM)来发送,用recvfd(用于SOCK_RAW, IPPROTO_ICMP)来接收,即收发可以是不同的描述符
(7) strncpy,strncmp与memcpy, memcmp是不同的,因为前者的实现是对“字符串”而言的,如果没有遇到\0,且没有到达最后,其中某一个大于另一个则返回,换句话说, 如果遇到了\0,就回直接出现结果,因此,不适合比较结构体(结构体中可能有\0,比较就会终止,而我要比较的是两个结构体的每一个字节),而memcpy则只是比较字节的大小,不管是否是字符串,是否结束,因此可以比较结构体;strncpy与memcpy也有类似的\0的问题。
(8)bind函数,如果地址没有给出,只给出了端口号,则内核会自动分配地址的。
(9)一些socket函数:
inet_ntop : 已知地址,想返回字符串表示
inet_pton : 已知字符串表示,想返回二进制地址
htons/ntohs : 端口号(或者两字节的什么东东), uint16_t
htonl/ntohl : 地址(或者四字节的什么东东), uint32_t
getaddrinfo : 已知要获取的主机的信息的ip(ipv4,ipv6均可)地址或者主机名字或者服务端口 号,返回关于主机的信息,包括ip地址,主机名(ai_canonname),地址长度,协 议,端口号,family等
(10) gettimeofday(struct timeval *tv, struct timezone *tz)微妙级别的运算,如本程序中的ms的运算就是通过此函数获得的。
(11) 最坑爹的是recvfrom函数(ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen)),如果过用sock_raw,其最后一个参数是长度。当把长度设置成小于16(ipv4的struct sockaddr_in的长度)时,src_addr得到的是全是0,而利用buf可以得到对方的地址,但是当长度大于16时,可以得到正确的地址(不是0了)------虽然因为addrlen参数是值-结果类型的参数,最后的结果都是16.
直接make就行了。
阅读(2212) | 评论(0) | 转发(0) |