IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> TCP/IP网络编程——习题答案 -> 正文阅读

[网络协议]TCP/IP网络编程——习题答案

第一章 理解网络编程和套接字


?

(1)?套接字在网络编程中的作用是什么?为什么称它为套接字?

网络编程就是编写程序让两台联网的计算机相互交换数据。在我们不需要考虑物理连接的情况下,我们只需要考虑如何编写传输软件。操作系统提供了名为“套接字”,套接字是网络传输传输用的软件设备
socket英文原意是插座:我们把插头插到插座上就能从电网获得电力供给,同样,为了与远程计算机进行数据传输,需要连接到Internet,而变成中的“套接字”就是用来连接该网络的工具

(2) 在服务器端创建套接字后,会依次调用listen函数和accept函数。请比较并说明两者作用

listen:将套接字转为可接受连接方式(监听套接字)
accept:受理连接请求,并且在没有连接请求的情况调用该函数,不会返回(阻塞)。直到有连接请求为止。二者存在逻辑上的先后关系

(3)Linux中,对套接字数据进行I/O时可以直接使用I/O相关函数;而在Windows中则不可以。原因为何?

Linux把套接字也看作是文件,所以可以用文件I/O相关函数;而Windows要区分套接字和文件,所以设置了特殊的函数

(4)创建套接字后一般会给它分配地址,为什么?为了完成地址分配需要调用哪些函数?

要在网络上区分来自不同机器的套接字,所以需要地址信息。分配地址是通过bind()函数实现

(5)Linux中的文件描述符与Windows的句柄实际上非常类似。请以套接字为对象说明他们的含义。

Linux的文件描述符是为了区分指定文件而赋予文件的整数值(相当于编号)。Windows的文件描述符其实也是套接字的整数值,其目的也是区分指定套接字。

(6)底层文件I/O函数与ANSI标准定义的文件I/O函数之间有何区别?

ANSI标准定义的输入、输出函数是与操作系统(内核)无关的以C标准写成的函数;相反,底层文件I/O函数是操作系统直接提供的。

标准I/O分为全缓冲,行缓冲,不缓冲三种形式;文件I/O为不带缓冲的I/O。

文件I/O主要针对文件操作,它操作的是文件描述符;标准I/O针对的是控制台,它操作的是字符流。对于不同设备得特性不一样,必须有不同api访问才最高效。

(7)参考本书给出的示例low_open.c和low_read.c,分别利用底层文件I/O和ANSI标准I/O编写文件复制程序。可任意指定复制程序的使用方法

先执行书上代码创建data.txt并写入内容"Let's go!\n"

#include?
#include?
#include?

void?error_handling(char*?message);

int?main(void)
{
	int?fd;
	char?buf[]?=?"Let's?go!\n";

	fd?=?open("data.txt",?O_CREAT?|?O_WRONLY?|?O_TRUNC);
	if?(fd?==?-1)
		error_handling("open()?error!");
	printf("file?descriptor:?%d?\n",?fd);

	if?(write(fd,?buf,?sizeof(buf))?==?-1)
		error_handling("write()?error!");

	close(fd);
	return?0;
}

void error_handling(char* message)
{  fputs(message, stderr);  fputc('\n', stderr);  exit(1);
}

用底层I/O编写:

    int?fd1,fd2;
	int?count?=?0;
	char?buf[20];

	fd1?=?open("data.txt",?O_RDONLY);
	if?(fd1?==?-1)
		error_handling("open()?error!");

	fd2=?open("data_copy.txt",?O_CREAT?|?O_WRONLY?);
	if?(fd2?==?-1)
		error_handling("open()?error!");

	while?((count?=?read(fd1,?buf,?20))?>?0)??????//每次读取20个字符
	{
		write(fd2,?buf,?count);
	}

	close(fd1);
	close(fd2);
	return?0;

用ANSI标准I/O编写:

	FILE*?fin;????//?源文件
	FILE*?fout;???//?目标文件
	char?buf[20];?//缓冲区设置为20
	int?count;??


	fin?=?fopen("data.txt",?"r");
	if?(NULL?==?fin)?	
		error_handling("open()?error!");

	fout?=?fopen("data_copy",?"aw");
	if?(NULL?==?fout)?	
		error_handling("open()?error!");
	
	while?((count?=?fread(buf,?1,?20,?fin))?>?0)
	{
		fwrite(buf,?1,?count,?fout);
	}

	fclose(fin);
	fclose(fout);
	return?0;

第二章:套接字类型与协议设置

(1)什么是协议?在收发数据中定义协议有何意义?

协议就是为了完成数据交换而定好的规则。因此,定义协议意味着对数据传输所必需的的规则进行定义。

(2)面向连接的TCP套接字传输特性有3点,请分别说明。

1.传输过程中数据不会丢失
2.按序传输数据
3.传输的数据不存在数据边界(Boundary)

(3)下面哪些是面向消息的套接字的特性?

a、c、e

a.传输数据可能丢失;c.以快速传递为目的;e.与面向连接的套接字不同,不存在连接的概念

(4)下列数据适合用哪些套接字传输?并给出原因

UDP 、TCP 、TCP
1.演唱会讲究实时性,稍微丢包也能够有算法补救(顶多画质下降),所以用UDP更好
2.文本文件讲究可靠传输,所以用TCP

3.支付这种敏感数据更需要可靠传输,所以用TCP

(5)何种类型的套接字不存在数据边界?这类套接字接收数据时需要注意什么?

连接指向型TCP套接字不存在数据边界。因此输入输出函数的响应次数不具有意义。重要的不是函数的响应次数,而是数据的收发量。需要保证在接收套接字的缓冲区填充满之前就从buffer里读取数据。也就是,在接收套接字内部,写入buffer的速度要小于读出buffer的速度。

(6)tcp_server.c和tcp_client.c中需要多次调用read函数读取服务器调用1次write函数传递的字符串。更改程序,使服务器端多次调用(次数自拟)write函数传输数据,客户端调用1次read函数进行读取。为达到这一目的,客户端需延迟调用read函数,因为客户端要等待服务器端传输所有数据。

/*****************************tcp_serv.c*********************************/
#include?<stdio.h>
#include?<stdlib.h>
#include?<string.h>
#include?<unistd.h>
#include?<arpa/inet.h>
#include?<sys/types.h>
#include?<sys/socket.h>

void?error_handling(char?*message);

int?main(int?argc,?char?*argv[])
{
	int?serv_sock;
	int?clnt_sock;

	struct?sockaddr_in?serv_addr;
	struct?sockaddr_in?clnt_addr;
	socklen_t?clnt_addr_size;

	char?message[]="Hello?World!";
	
	if(argc!=2){
		printf("Usage?:?%s?<port>\n",?argv[0]);
		exit(1);
	}
	
	serv_sock=socket(PF_INET,?SOCK_STREAM,?0);
	if(serv_sock?==?-1)
		error_handling("socket()?error");
	
	memset(&serv_addr,?0,?sizeof(serv_addr));
	serv_addr.sin_family=AF_INET;
	serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
	serv_addr.sin_port=htons(atoi(argv[1]));
	
	if(bind(serv_sock,?(struct?sockaddr*)?&serv_addr,?sizeof(serv_addr))==-1)
		error_handling("bind()?error");?
	
	if(listen(serv_sock,?5)==-1)
		error_handling("listen()?error");
	
	clnt_addr_size=sizeof(clnt_addr);??
	clnt_sock=accept(serv_sock,?(struct?sockaddr*)&clnt_addr,&clnt_addr_size);
	if(clnt_sock==-1)
		error_handling("accept()?error");??
	
	write(clnt_sock,?message,?4);           //多次调用write函数传输数据
	write(clnt_sock,?message+4,?4);
	write(clnt_sock,?message+8,?4);
	write(clnt_sock,?message+12,?sizeof(message)-12);

	close(clnt_sock);
	return?0;
}

void?error_handling(char?*message)
{
	fputs(message,?stderr);
	fputc('\n',?stderr);
	exit(1);
}

/*****************************tcp_clnt.c*********************************/
#include?<stdio.h>
#include?<stdlib.h>
#include?<string.h>
#include?<unistd.h>
#include?<arpa/inet.h>
#include?<sys/types.h>
#include?<sys/socket.h>

void?error_handling(char?*message);

int?main(int?argc,?char*?argv[])
{
	int?sock;
	struct?sockaddr_in?serv_addr;
	char?message[30];
	int?str_len=0;
	int?idx=0,?read_len=0,?i;
	
	if(argc!=3){
		printf("Usage?:?%s?<IP>?<port>\n",?argv[0]);
		exit(1);
	}
	
	sock=socket(PF_INET,?SOCK_STREAM,?0);
	if(sock?==?-1)
		error_handling("socket()?error");
	
	memset(&serv_addr,?0,?sizeof(serv_addr));
	serv_addr.sin_family=AF_INET;
	serv_addr.sin_addr.s_addr=inet_addr(argv[1]);
	serv_addr.sin_port=htons(atoi(argv[2]));
		
	if(connect(sock,?(struct?sockaddr*)&serv_addr,?sizeof(serv_addr))==-1)?
		error_handling("connect()?error!");

	for(i=0;?i<100;?i++)		 //busy?waiting!!
		printf("Wait?time?%d?\n",?i);

	read(sock,?message,?sizeof(message));
	printf("Message?from?server:?%s?\n",?message);
	close(sock);
	return?0;
}

void?error_handling(char?*message)
{
	fputs(message,?stderr);
	fputc('\n',?stderr);
	exit(1);
}

第三章 地址族与数据序列

(1)IP地址族IPv4和IPv6有何区别?在何种背景下诞生了IPv6?

IPV4是4字节地址族,IPV6是16字节地址族。IPV6的诞生是为了应对2010年前后IP地址耗尽的问题而提出的标准

(2)通过IPV4网络ID、主机ID及路由器的关系说明向公司局域网中的计算机传输数据的过程

向目标主机传输数据,首先向目标IP所属的网络传输数据。此时使用的是IP地址中的网络ID。数据传到路由器,路由器将参照IP地址的主机号查找路由表,从对应的网口发送数据,数据经过路由器转发最终送到目标主机

(3)套接字地址分为IP地址和端口号。为什么需要IP地址和端口号?或者说,通过IP可以区分哪些对象?通过端口号可以区分哪些对象?

IP地址是为了区分网络上的主机。端口号是区分同一主机下的不同的SOCKET,以确保程序进程都能准确收发数据。

(4)请说明IP地址分类方法,并说出下面这些IP地址的分类

C类、A类、B类

根据第一字节格式分类:

(5)计算机通过路由器或交换机连接到互联网。请说出路由器和交换机的作用

路由器:是连接两个或多个网络的硬件设备,在网络间起网关的作用,是读取每一个数据包中的地址然后决定如何传送的专用智能性的网络设备。(作用于网络层,寻址,转发(依靠 IP 地址)
交换机:是一种用于电(光)信号转发的网络设备。(一般作用于链路层,过滤,转发(依靠 MAC 地址))

(6)什么是知名端口?其范围是多少?知名端口中具有代表性的HTTP合同FTP端口号各是多少?

“知名端口(Well-known PROT)”是指预定分配给特定操作的端口。其范围是0~1023,其中最知名的端口是HTTP:80端口和TCP:21

(7)题目大概意思是:为什么bind中第二个参数是sockaddr,但是传入的是sockaddr_in

bind函数第二个参数类型sockaddr结构体,很难分配IP地址和端口号的空间大小(因为结构体sockaddr并非只为IPv4设计,所以要兼容),所以sockaddr结构体内将IP地址和端口号合并到一起,用一个成员 sa_data 表示。因此对于不同类型网络的IP地址和PORT号的分配是可先通过sockaddr_in完成,之后再强制转换成sockaddr类型(因为两个结构体的长度相同,都是16字节,强制转换类型时不会丢失字节,也没有多余的字节)

(8)请解释大端序、小端序、网络字节序,并说明为何需要网络字节序

小端序是把高位字节存储到高位地址上;大端序是把高位字节存储到低位地址上。因为保存栈的方式有差异,所以对网络传输数据的过程制定了标准,这就是“网路字节序”。而且,在网络字节序中,数据传输的标准是“大端序”

(9)大端计算机希望将4字节整型数据12传到小端序计算机。请说出数据传输过程中发生的字节序变换过程

因为网络字节序的顺序标准是“大端序”,所以大端序的计算机在网络传输中不需要先转换字节顺序,直接传输。但是接受数据的是小端序计算机,因此,要经过网络转本地序的过程,再保存到存储设备上

(10)怎么表示回送地址?其含义是什么?如果向回送地址传输数据将会发生什么情况?

回送地址表示计算机本身,为127.0.0.1。因此,如果将数据传送到IP地址127.0.0.1,数据不进行网络传输而是直接返回。

第四章 基于TCP的服务器端/客户端(1)

(1)请说明TCP/IP的4层协议栈,并说明TCP和UDP套接字经过的层级结构差异

链路层—>IP层—>TCP层—>应用层
链路层—>IP层—>UDP层—>应用层

(2)请说出TCP/IP协议栈中链路层和IP层的作用,并给出两者关系。

数据链路层通过各种控制协议,将有差错的物理信道变为无差错的、能可靠传输数据帧的数据链路。为IP 层提供数据传送服务
网络层通过路由选择算法,为分组选择最适当的路径,实现两个端系统之间的数据透明传送

(3)为何需要把TCP/IP协议栈分成4层(或7层)?结合开放式系统回答

ARPANET 的研制经验表明,对于复杂的计算机网络协议,其结构应该是层次式的。

分层的好处:隔层之间是独立的,灵活性好,结构上可以分隔开,易于实现和维护,能促进标准化工作

(4)客户端调用connect函数向服务器端发送连接请求。服务器端调用哪个函数后,客户端可以调用connect函数?

调用listen函数设置好服务端监听套接字后

(5)什么时候创建连接请求等待队列?它有何作用?与accept有什么关系

调用listen函数时创建了连接请求等待队列。它是存储客户端连接请求信息的空间。accept函数调用后,将从连接请求队列中取出连接请求信息,并与相应客户端建立连接。

(6)客户端中为何不需要调用bind函数分配地址?如果不调用bind函数,那何时、如何向套接字分配IP地址和端口号?

客户端是请求连接的程序,不是一个接收连接的程序。所以,服务器的地址信息是更重要的因素,没有必要通过bind函数明确地分配地址信息。但是,要想和服务器通信,必须将自己的地址信息分配到套接字上,因此,在connect函数调用时,自动把IP地址和端口号输入到套接字上。

(7)把第1章的hello_server.c和hello_server_win.c改成迭代服务器端,并理由客户端测试更改是否准确

#include?<stdio.h>
#include?<stdlib.h>
#include?<string.h>
#include?<unistd.h>
#include?<arpa/inet.h>
#include?<sys/socket.h>

void?error_handling(char?*message);

int?main(int?argc,?char?*argv[])
{
	int?serv_sock;
	int?clnt_sock;

	struct?sockaddr_in?serv_addr;
	struct?sockaddr_in?clnt_addr;
	socklen_t?clnt_addr_size;

	char?message[]="Hello?World!";
	
	if(argc!=2){
		printf("Usage?:?%s?<port>\n",?argv[0]);
		exit(1);
	}
	
	serv_sock=socket(PF_INET,?SOCK_STREAM,?0);
	if(serv_sock?==?-1)
		error_handling("socket()?error");
	
	memset(&serv_addr,?0,?sizeof(serv_addr));
	serv_addr.sin_family=AF_INET;
	serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
	serv_addr.sin_port=htons(atoi(argv[1]));
	
	if(?bind(serv_sock,?(struct?sockaddr*)?&serv_addr,?sizeof(serv_addr))==-1?)
		error_handling("bind()?error");?
	
	if(?listen(serv_sock,?5)==-1?)
		error_handling("listen()?error");
	
	clnt_addr_size=sizeof(clnt_addr);??
	
	while(1)
	{
		clnt_sock=accept(serv_sock,?(struct?sockaddr*)&clnt_addr,&clnt_addr_size);
		if(clnt_sock==-1)
			break;??
		
		write(clnt_sock,?message,?sizeof(message));
		close(clnt_sock);
	}
	close(serv_sock);
	return?0;
}

void?error_handling(char?*message)
{
	fputs(message,?stderr);
	fputc('\n',?stderr);
	exit(1);
}


?

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-07-10 14:49:19  更:2021-07-10 14:49:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/18 9:45:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码