《TCP/IP网络编程》课后练习答案第一部分6~10章 尹圣雨

第六章 基于UDP的服务器端/客户端

  1. UDP为什么比TCP速度快?为什么TCP数据传输可靠而UDP数据传输不可靠?

    UDP和TCP不同,不进行流量控制。由于该控制涉及到套接字的连接和结束,以及整个数据收发过程,因此,TCP传输的数据是可以信赖的。相反,UDP不进行这种控制,因此无法信任数据的传输,但正因UDP不进行流量控制,所以比TCP更快

  2. bce

  3. UDP数据包向对方主机的UDP套接字传递过程中,IP和UDP分别负责哪些部分?

    IP负责链路选择。UDP负责端到端的传输

  4. UDP一般比TCP快,但根据交换数据的特点,其差异可大可小。请说明何种情况下UDP的性能优于TCP

    UDP与TCP不同,不经过连接以及断开SOCKET的过程,因此,在频繁的连接及断开的情况下,UDP的数据收发能力会凸显出更好的性能。

  5. 客户端TCP套接字调用connect函数时自动分配IP和端口号。UDP中不调用bind函数,那何时分配IP和端口号?

    首次调用sendto函数时,发现尚未分配信息,则给相应的套接字自动分配IP和端口号

  6. TCP客户端必须调用connect函数,而UDP中可以选择性调用。请问,在UDP中调用connect函数有哪些好处?

    每当以UDP套接字为对像调用sendto函数时,都要经过以下过程

    • 第一阶段:为目标UDP注册端口和IP
    • 第二阶段:数据传输
    • 第三阶段:删除UDP注册的IP和端口信息

    其中,只要调用connect函数,就可以忽略每次传输数据时反复进行的第一阶段和第三阶段。然而,调用connect函数并不意味着经过连接过程,只是将IP地址和端口号指定在UDP的发送对象上。这样connect函数使用后,还可以用write、read函数进行数据处理,而不必使用sendto、recvfrom

  7. 收发的消息均要输出到控制台窗口

    /********************************uchar_server.c***********************************/
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    
    #define BUF_SIZE 30
    void error_handling(char *message);
    
    int main(int argc, char *argv[])
    {
    	int serv_sock;
    	char message[BUF_SIZE];
    	int str_len;
    	socklen_t clnt_adr_sz;
    	
    	struct sockaddr_in serv_adr, clnt_adr;
    	if(argc!=2){
    		printf("Usage : %s <port>\n", argv[0]);
    		exit(1);
    	}
    	
    	serv_sock=socket(PF_INET, SOCK_DGRAM, 0);
    	if(serv_sock==-1)
    		error_handling("UDP socket creation error");
    	
    	memset(&serv_adr, 0, sizeof(serv_adr));
    	serv_adr.sin_family=AF_INET;
    	serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
    	serv_adr.sin_port=htons(atoi(argv[1]));
    	
    	if(bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)
    		error_handling("bind() error");
    	
    	clnt_adr_sz=sizeof(clnt_adr);
    	while(1) 
    	{
    		str_len=recvfrom(serv_sock, message, BUF_SIZE, 0, 
    								(struct sockaddr*)&clnt_adr, &clnt_adr_sz);
    		message[str_len]=0;
    		printf("Message from client: %s", message);
    
    		fputs("Insert message(q to quit): ", stdout);
    		fgets(message, sizeof(message), stdin);
    		if(!strcmp(message,"q\n") || !strcmp(message,"Q\n"))	
    			break;
    
    		sendto(serv_sock, message, strlen(message), 0, 
    								(struct sockaddr*)&clnt_adr, clnt_adr_sz);
    	}	
    	close(serv_sock);
    	return 0;
    }
    
    void error_handling(char *message)
    {
    	fputs(message, stderr);
    	fputc('\n', stderr);
    	exit(1);
    }
    
    
    /********************************uchar_client.c***********************************/
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    
    #define BUF_SIZE 30
    void error_handling(char *message);
    
    int main(int argc, char *argv[])
    {
    	int sock;
    	char message[BUF_SIZE];
    	int str_len;
    	socklen_t adr_sz;
    	
    	struct sockaddr_in serv_adr, from_adr;
    	if(argc!=3){
    		printf("Usage : %s <IP> <port>\n", argv[0]);
    		exit(1);
    	}
    	
    	sock=socket(PF_INET, SOCK_DGRAM, 0);   
    	if(sock==-1)
    		error_handling("socket() error");
    	
    	memset(&serv_adr, 0, sizeof(serv_adr));
    	serv_adr.sin_family=AF_INET;
    	serv_adr.sin_addr.s_addr=inet_addr(argv[1]);
    	serv_adr.sin_port=htons(atoi(argv[2]));
    	
    	while(1)
    	{
    		fputs("Insert message(q to quit): ", stdout);
    		fgets(message, sizeof(message), stdin);     
    		if(!strcmp(message,"q\n") || !strcmp(message,"Q\n"))	
    			break;
    		
    		sendto(sock, message, strlen(message), 0, 
    					(struct sockaddr*)&serv_adr, sizeof(serv_adr));
    		adr_sz=sizeof(from_adr);
    		str_len=recvfrom(sock, message, BUF_SIZE, 0, 
    					(struct sockaddr*)&from_adr, &adr_sz);
    
    		message[str_len]=0;
    		printf("Message from server: %s", message);
    	}	
    	close(sock);
    	return 0;
    }
    
    void error_handling(char *message)
    {
    	fputs(message, stderr);
    	fputc('\n', stderr);
    	exit(1);
    }
    

第七章 优雅地断开套接字连接

  1. 解释TCP中“流”的概念。UDP中能否形成流?请说明原因

    TCP的流指,两台主机通过套接字建立连接后进入可交换数据的状态,也称为“流形成的状态”。而对于UDP来说,不存在流,因为两个SOCKET不能相互连接

  2. Linux中的close函数或Windows中的closesocket函数属于单方面断开连接的方法,有可能带来一些问题。什么是单方面断开连接?什么情况下会出现问题?

    单方面的断开连接意味着套接字无法再发送数据。一般在对方有剩余数据为发送完成时,断开己方连接,会造成问题。

  3. 什么是半关闭?针对输出流执行半关闭的主机处于何种状态?半关闭会导致对方主机接收什么信息?

    半关闭是指只完成输入和输出流中的一个。而且,如果对输出流进行半关闭,EOF无法被传送到对方主机,己方套接字无法传送数据,但可以接收对方主机传送的数据。

第八章 域名及网络地址

  1. bd

  2. 如果网络上没有特别的限制,可以将与本地网络相连的DNS服务器指定为其他完好的DNS服务器。因此,东秀提议的方法可能成为解决方法。也就是说,静洙可以不去网吧

    • 计算机向DNS服务器询问IP地址
    • 默认DNS服务器没有IP地址信息,因此向DNS主机发出询问
    • DNS查询服务器从其更上级的DNS服务器接收IP地址信息
    • DNS查询服务器将查到的IP地址逐级返还给主机
    • 网络浏览器访问接收到的IP地址网站

第九章 套接字的多种可选项

  1. 下列关于Time-wait状态的说法错误的是?acd(作者的答案就acd,至于d选项是否有问题,见仁见智)

  2. TCP_NODELAY可选项与Nagle算法有关,可通过它禁止Nagle算法。请问何时应考虑禁用Nagle算法?结合收发数据的特性给出说明

    根据传输数据的特性,网络流量未受太大影响时,不使用Nagle算法要比使用它时传输速度快。例如“传输大文件数据”。将文件数据传入输出缓冲不会花太多时间,因此,即便不使用Nagle算法那,也会在装满输出缓冲时传输数据包。这不仅不会增加数据包的数量,反而会在无需等待ACK的前提下连续传输,因此可以大大提高传输速度。

第十章 多进程服务器端

  1. 下列关于进程的说法错误的是?cd

  2. 调用fork函数将创建子进程,以下关于子进程描述错误的是?acd(a选项我测试过,真的不会销毁)

  3. 创建子进程时将复制父进程的所有内容,此时的复制对象也包含套接字文件描述符。编写程序验证复制的文件描述符整数值是否与原文件描述符整数值相同。

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/socket.h>
    
    int main(int argc, char *argv[])
    {
    	pid_t pid;
    	int sockfd=socket(PF_INET, SOCK_STREAM, 0);
    	
    	pid=fork();		
    	
    	if(pid==0)
    		printf("Child sock fd: [%d] \n", sockfd);
    	else
    		printf("Parent sock fd: [%d] \n", sockfd);
    	return 0;
    }
    
    显示
    Parent sock fd: [3] 
    Child sock fd: [3] 
    
    
  4. 请说明进程变为僵尸进程的过程及预防措施

    僵尸进程是子进程。在子进程结束时,其返回值会传到操作系统,直到返回值被其父进程接收为止,该(子)进程会一直作为僵尸进程存在。所以,为了防止这种情况的发生,父进程必须明确接收子进程结束时的返回值。

  5. 编写程序使其每隔1秒输出简单字符串,并适用于上述时间处理器注册代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    
    void ctrl_handler(int sig);
    
    int main(int argc, char *argv[])
    {
    	struct sigaction act;
    	act.sa_handler=ctrl_handler;
    	sigemptyset(&act.sa_mask);
    	act.sa_flags=0;
    	sigaction(SIGINT, &act, 0);
    
    	while(1)
    	{
    		sleep(1);
    		puts("Have a nice day~");
    	}
    
    	return 0;
    }
    
    
    void ctrl_handler(int sig)
    {
    	char ex;
    	fputs("Do you want exit(Y to exit)? ", stdout);
    	scanf("%c", &ex);
    	if(ex=='y' || ex=='Y')
    		exit(1);
    }
    
    
  • 11
    点赞
  • 71
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
编辑推荐 本书是网络构建原型——4.4BSD的建造者的倾力之作,《TCP/IP解析》中的第1卷,主要讲述TCP/IP协议方面的内容。与其他的TCP/IP书藉的最大不同在于,本书不仅仅讲述了RFCS的标准协议,而且结合大量实例讲述了TCP/IP协议包的定义原因及在各种不同的操作系统中(如Sunos4.1.3、Soloris2.2、AIX3.2.2)的应用与工作方式,这样可以以动态方式讲述TCP/IP的知识,使读者可以轻松掌握TCP/IP的知识:路由协议、寻址协议、组控制协议、简单邮件传输协议等。全书内容实用性强,是在校生学习TCP/IP知识的良师益友。 内容简介  《TCP/IP详解,卷1:协议》是一本完整而详细的TCP/IP协议指南。描述了属于每一层的各个协议以及它们如何在不同操作系统中运行。作者用Lawrence Berkeley实验室的tcpdump程序来捕获不同操作系统和TCP/IP实现之间传输的不同分组。对tcpdump输出的研究可以帮助理解不同协议如何工作。 本书适合作为计算机专业学生学习网络的教材和教师参考书。也适用于研究网络的技术人员。 作者简介 W.Richard Stevens(1951-1999)是一位非常受人尊敬的专家,除了《TCP/IP详解》三卷本外,他还有其他两部最为畅销的作品:《UNIX环境高级编程》和《UNIX网络编程》(两卷本)。 目录 译者序 前言 第1章 概述 1 1.1 引言 1 1.2 分层 1 1.3 TCP/IP的分层 4 1.4 互联网的地址 5 1.5 域名系统 6 1.6 封装 6 1.7 分用 8 1.8 客户-服务器模型 8 1.9 端口号 9 1.10 标准化过程 10 1.11 RFC 10 1.12 标准的简单服务 11 1.13 互联网 12 1.14 实现 12 1.15 应用编程接口 12 1.16 测试网络 13 1.17 小结 13 第2章 链路层 15 2.1 引言 15 2.2 以太网和IEEE 802封装 15 2.3 尾部封装 17 2.4 SLIP:串行线路IP 17 2.5 压缩的SLIP 18 2.6 PPP:点对点协议 18 2.7 环回接口 20 2.8 最大传输单元MTU 21 2.9 路径MTU 21 2.10 串行线路吞吐量计算 21 2.11 小结 22 第3章 IP:网际协议 24 3.1 引言 24 3.2 IP首部 24 3.3 IP路由选择 27 3.4 子网寻址 30 3.5 子网掩码 32 3.6 特殊情况的IP地址 33 3.7 一个子网的例子 33 3.8 ifconfig命令 35 3.9 netstat命令 36 3.10 IP的未来 36 3.11 小结 37 第4章 ARP:地址解析协议 38 4.1 引言 38 4.2 一个例子 38 4.3 ARP高速缓存 40 4.4 ARP的分组格式 40 4.5 ARP举例 41 4.5.1 一般的例子 41 4.5.2 对不存在主机的ARP请求 42 4.5.3 ARP高速缓存超时设置 43 4.6 ARP代理 43 4.7 免费ARP 45 4.8 arp命令 45 4.9 小结 46 第5章 RARP:逆地址解析协议 47 5.1 引言 47 5.2 RARP的分组格式 47 5.3 RARP举例 47 5.4 RARP服务器的设计 48 5.4.1 作为用户进程的RARP服务器 49 5.4.2 每个网络有多个RARP服务器 49 5.5 小结 49 第6章 ICMP:Internet控制报文协议 50 6.1 引言 50 6.2 ICMP报文的类型 50 6.3 ICMP地址掩码请求与应答 52 6.4 ICMP时间戳请求与应答 53 6.4.1 举例 54 6.4.2 另一种方法 55 6.5 ICMP端口不可达差错 56 6.6 ICMP报文的4.4BSD处理 59 6.7 小结 60 第7章 Ping程序 61 7.1 引言 61 7.2 Ping程序 61 7.2.1 LAN输出 62 7.2.2 WAN输出 63 7.2.3 线路SLIP链接 64 7.2.4 拨号SLIP链路 65 7.3 IP记录路由选项 65 7.3.1 通常的例子 66 7.3.2 异常的输出 68 7.4 IP时间戳选项 69 7.5 小结 70 第8章 Traceroute程序 71 8.1 引言 71 8.2 Traceroute 程序的操作 71 8.3 局域网输出 72 8.4 广域网输出 75 8.5 IP源站选路选项 76 8.5.1 宽松的源站选路的traceroute程序示例 78 8.5.2 严格的源站选路的traceroute程序示例
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值