计算机网络课程设计(3)

2019-03-03 16:08

设置随同Echo请求一起发送的可选数据长度处理命令行参数为SIGALARM信号建立一个处理程序处理主机名参数调用readloop处理分组

2)readloop函数

创建套接口设置套接口缓冲区大小发送第一个分组读取返回给ICMP原始套接口的每个分组记录收到分组的时间调用proc来处理这些分组

3)proc函数

11

获取ICMP头部指针检查ICMP Echo replay输出收到的所有ICMP消息

4)send函数

构造ICMP消息计算校验和发送数据报 四、程序核心功能的实现机制

程序分为两大部分:一部分读取收到的所有消息,并输出ICMP Echo replay消息,另一部分每隔一秒钟发送一个Echo消息。另一部分由SIGALARM信号每秒驱动一次。

首先需要在main()函数里面的循环getopt()的参数里面增加参数,本次实验加的是b,c,h,i,q,s,t,v.然后不同的分支执行不同的操作。

在主函数的最后也就是readloop()函数之后再加一个statistics()数据统计函数,目的是在readloop()中返回时直接执行这个函数。 五、程序源代码(核心部分) 黑体字部分是修改部分

int main(int argc, char **argv) {

extern char *optarg; int c;

struct addrinfo *ai; char *e;

opterr = 0; /* don't want getopt() writing to stderr */

while ( (c = getopt(argc, argv, \ switch (c) { case 'b':

options |= F_BROADCAST; break; case 'c':

npackets = strtol(optarg, &e, 10);

12

if (npackets <= 0 || *optarg == '\\0' || *e != '\\0') errx(1, \ break; case 'h': usage(); exit(1); break;

case 'i': /* wait between sending packets */ interval = strtol(optarg, &e, 10);

if (interval <= 0 || *optarg == '\\0' || *e != '\\0') errx(1, \ options |= F_INTERVAL; break; case 'q':

options |= F_QUIET; break;

case 's': /* size of packet to send */ datalen = strtol(optarg, &e, 10);

if (datalen <= 0 || *optarg == '\\0' || *e != '\\0') errx(1, \ if (datalen > MAXPACKET)

errx(1, \value too large, maximum is MAXPACKET);

break; case 't':

ttl = strtol(optarg, &e, 10);

if (datalen <= 0 || *optarg == '\\0' || *e != '\\0') errx(1, \ options |= F_TTL; break; case 'v':

options |= F_VERBOSE; break; //case '?':

//err_quit(\ default: usage(); } }

if (optind != argc-1) usage(); host = argv[optind]; pid = getpid();

signal(SIGALRM, sig_alrm);

ai = host_serv(host, NULL, 0, 0);

if (options & F_BROADCAST)

13

%d\ printf(\

printf(\ Sock_ntop_host(ai->ai_addr, ai->ai_addrlen), datalen);

/* 4initialize according to protocol */ if (ai->ai_family == AF_INET) { pr = &proto_v4; #ifdef IPV6

} else if (ai->ai_family == AF_INET6) { pr = &proto_v6;

if (IN6_IS_ADDR_V4MAPPED(&(((struct sockaddr_in6 *) ai->ai_addr)->sin6_addr))) err_quit(\#endif } else

err_quit(\

(void)signal(SIGINT, onint);

pr->sasend = ai->ai_addr;

pr->sarecv = calloc(1, ai->ai_addrlen); pr->salen = ai->ai_addrlen;

readloop();

statistics(); exit(0); }

////////////////////////////////////////////////////////////// void readloop(void) {

int size;

char recvbuf[BUFSIZE]; socklen_t len; ssize_t n; struct timeval tval; int yes = 1;

sockfd = socket(pr->sasend->sa_family, SOCK_RAW, pr->icmpproto);

setuid(getuid()); /* don't need special permissions any more */

size = 60 * 1024; /* OK if setsockopt fails */

setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));

if (options & F_TTL)

14

setsockopt(sockfd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)); if (options & F_BROADCAST) setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes));

sig_alrm(SIGALRM); /* send first packet */ for ( ; ; ) {

len = pr->salen;

n = recvfrom(sockfd, recvbuf, sizeof(recvbuf), 0, pr->sarecv, &len); if (n < 0) {

if (errno == EINTR) continue; else

err_sys(\ }

gettimeofday(&tval, NULL);

(*pr->fproc)(recvbuf, n, &tval);

if (npackets && nreceived >= npackets) break; } }

///////////////////////////////////////////////////////////// void usage() {

err_quit(\ [-b] [-q] [-s packetsize]\\n\\

[-t ttl] [-v] [-h] \}

///////////////////////////////////////////////////////////// void statistics()

{ printf(\

printf(\packets transmitted, %ld received , %%%d lost\\n\nsend, nreceived, (nsend-nreceived)/nsend*100); close(sockfd); exit(1); }

六、程序扩展功能的需求分析与实现

-b分支,主要是允许ping广播地址,设置option |=F_BROADCAST,然后在reedloop()函数

里面增加

if (options & F_BROADCAST)

setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes));语句 -c分支,主要是要获取包的数量,通过npackets = strtol(optarg, &e, 10);来实现。 -h分支,主要用来显示使用帮组信息的,只需要通过函数usage(),就可显示帮助信息。

15


计算机网络课程设计(3).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:我国房产税制度设计与探讨

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: