…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
线
…
…
…
…
…
…
…
…
订
…
…
…
…
…
…
…
…
装
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
�
期
日
核
审
�
�
名
签
人
核
审
�
期
日
卷
制
�
名
签
人
卷
制
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
湘潭大学2010 年下学期2008级
《网络协议分析
及编程Ⅰ》课程考试试卷
�A卷� 适用年级专业 2008级网络工程专业
考试方式 闭卷 考试时间 120 分钟
学院 专业 班级
学号 姓名
三
二
一
题
号
得
分
………………………………………………………………………………………………………………………
阅卷
教师
总分
五
四
得
分
一、本题中共有 30 个空格�要求全部解答�每个空格 2 分�满分 60 分。每
个空格对应一个序号�有 A、B、C、D 四个选项�请选择一个最恰当的选
项作为解答�写在答卷的相应序号栏内。
B�当前位置
D�上一次操作的字节数
●以下关于客户/服务器应用软件设计参数化的叙述中�错误的是__(1)__。
(1)�A�客户应用软件应当提供允许用户指定目的机器的参数
B�客户应用软件应当提供允许用户指定目的协议端口号的参数
C�服务器应用软件应当提供允许用户指定本地机器的参数
D�服务器应用软件应当提供允许用户指定本地协议端口号的参数
●在使用有状态交互的文件服务器环境中�有状态文件服务器的状态信息表中不必包含
的信息字段是__(2)__。
(2)�A�文件名
C�上一次操作
●以下关于有状态服务器的标识客户的方法的叙述中�错误的是__(3)__。
(3)�A�端点方法通常使用用客户的 I P 地址和协议端口等端点信息标识状态表条目
B�句柄方法通常使用一个小整数标识状态表条目
C�端点方法的缺点是由网络故障引发的客户连接变化会导致状态信息无效
D�句柄方法的缺点是由网络故障引发的客户连接变化会导致句柄无效
●针对套接字�socket�的系统数据结构含有许多字段�当应用进程调用 socket 后�通
常会在字段__(4)__中填入值�而其他字段的值必须使用其他系统调用才会填上。
(4)�A�Family, Sevice
C�Local port, Remote port
●以下程语句中�将 IP 地址“192.168.0.1” 填入到一个已经声明为 sockaddr_in 结构的
TCP/IP 通信端点 sockfd 的 I P 地址字段�正确的是__(5)__。
(5)�A�sockfd.sin_addr = “192.168.0.1”;
B�sockfd.sin_addr.s_addr = “192.168.0.1”;
C�sockfd.sin_addr = inet_addr(“192.168.0.1”);
D�sockfd.sin_addr.s_addr = inet_addr(“192.168.0.1”);
B�Local I P, Remote IP
D�Local I P, Local port
�第 1 页 共 14 页�
B�UDP 服务器
D�TCP 服务器户
●以下列语句中�将端口号 2010 填入到一个已经声明为 sockaddr_in 结构的 TCP/IP 通
信端点 sockfd 的端口号字段�正确的是__(6)__。
(6)�A�sockfd.sin_port = 2010;
B�sockfd.sin_port = htonl(2010);
C�sockfd.sin_port = htons(“2010”);
D�sockfd.sin_port = htons((unsigned short)atoi(“2010”));
●以下语句序列中�__(7)__将创建一个 UDP 通信端点 sock。
(7)�A�int sockfd; sock = socket(PF_INET, SOCK_STREAM, 0);
B�int sockfd; sock = socket(PF_INET, SOCK_DGRAM, 0);
C�int sockfd; sock = socket(PF_INET, SOCK_RAW, 0);
D�int sockfd; sock = socket(PF_I NET, SOCK_UDP, 0);
●以下关于客户调用 connect 系统调用的叙述中�错误的是__(8)__。
(8)�A�TCP 客户调用 connect 将激发 TCP 三次握手方式过程
B�UDP 客户调用 connect 只在套接字的数据结构中记录远程端点地址
C�无论 TCP 还是 UDP 客户调用 connect 都会检测远程端点地址的合法性
D�客户调用 connect 之前不必调用 bind 指定本地 IP 地址与本地协议端口
●以下情况下�__(9)__不能使用 read/ write 来接收/发送数据的是。
(9)�A�连接模式的 UDP 客户
C�TCP 客户
●以下情况下�__(10)__接收数据时必须且仅须调用 recvfrom 一次就可以获得由发送方
发送的一个完整报文。
(10)�A�TCP 客户
C�UDP 客户
●一个 TCP 客户的套接字 sockfd 发送完最后一个请求�但服务器对该请求的响应中有
大量的数据需要传递�此时�客户应当使用__(11)__关闭套接字。
(11)�A�close(sockfd)
C�shutdown(sockfd, 1)
●以下关于调用 bind 的叙述中�错误的是__(12)__。
(12)�A�应用进程调用 bind 时为套接字指定端口号为 0�那么�TCP/IP 协议软件就会
为该套接字选择一个临时的端口
B�应用进程调用 bind 时为套接字指定一个非 0 端口�如果此端口与熟知端口冲
突�那么�TCP/IP 协议软件就会为该套接字重新选择端口号
C�应用进程调用 bind 时为套接字指定 IP 地址为通配地址 INADDR_ANY�那么�
TCP/IP 协议软件就会为该套接字选择一个本地 IP 地址
D�TCP 服务器调用 bind 时为套接字指定特定的 IP 地址�那么�这就限定了该套
接字只能接收那些目的为此特定 IP 地址的客户连接。
●以下关于调用 listen 的叙述中�错误的是__(13)__。
(13)�A�listen 只能由 TCP 服务器调用
B�TCP 服务器调用 listen 将套接字置于被动模式
C�调用 listen 通常应该在调用 socket 之后�并在调用 bind 之前
D�listen 调用的第二个参数规定了 TCP/IP 协议软件应该为相应的套接字排队的最
大连接个数
●系统调用 accept 的函数原型如下�
B�shutdown(sockfd, 0)
D�shutdown(sockfd, 2)
B�TCP 服务器
D�UDP 服务器
int accept (int, struct sockaddr * , socklen_t * );
以下关于调用 accept 的叙述中�错误的是__(14)__。
(14)�A�accept 只能由 TCP 服务器调用
�第 2 页 共 14 页�
B�调用 accept 时�accept 的第二个参数通常是空指针
C�如果调用 accept 时没有任何连接请求到达�那么 accept 调用失败
D�如果 accept 调用成功�那么对端进程的协议地址由第二个参数的指针指定
●系统调用 recvfrom 的函数原型如下�
ssize_t recvfrom(int, void * , size_t, int, struct sockaddr * , socklen_t * );
以下关于调用 recvfrom 的叙述中�错误的是__(15)__。
(15)�A�调用 recvfrom 时�recvfrom 的第四个参数 flag 通常置为 0
B�调用 recvfrom 时�的第五个参数通常是空指针
C�如果调用 recvfrom 时没有任何数据到达�那么 accept 调用的返回值为 0
D�如果 recvfrom 调用成功�那么对端进程的协议地址由第五个参数的指针指定
● 以 下 对 于 库 函 数 gethostbyname 调 用 的 语 句 序 列 中 � __(16)__ 将 获 得 主 机
“www.xtu.edu.cn”的 IP 地址并采用点分十进制表示的形式输出。
(16)�A�struct hostent * phe;
phe = gethostbyname("www.xtu.edu.cn");
printf("IP Adress: %d.%d.%d.%d\ n", phe-> h_addr);
B�struct hostent * phe;
phe = gethostbyname("www.xtu.edu.cn");
printf("IP Adress: %d.%d.%d.%d\ n", * phe-> h_addr);
C�struct hostent * phe;
const u_char * p;
phe = gethostbyname("www.xtu.edu.cn");
p = (const u_char * ) phe-> h_addr;
printf("I P Adress: %d.%d.%d.%d\n", p[ 3] , p[ 2] , p[ 1] , p[ 0] );
D�struct hostent * phe;
const u_char * p;
phe = gethostbyname("www.xtu.edu.cn");
p = (const u_char * ) phe-> h_addr;
printf("IP Adress: %d.%d.%d.%d\ n", * p, * (p+ 1), * (p+ 2), * (p+ 3));
●以下对于库函数 getservbyname 调用的语句序列中�__(17)__ 将获得 FTP 服务的端
口号并产生合适的输出。
(17)�A�struct servent * pse;
pse = getservbyname(“ftp”, “udp”);
printf("ftp port: %d\ n", pse-> s_port);
B�struct servent * pse;
pse = getservbyname(“ftp”, “udp”);
printf("ftp port: %d\ n", ntohs(pse-> s_port));
C�struct servent * pse;
pse = getservbyname(“ftp”, “tcp”);
printf("ftp port: %d\ n", pse-> s_port);
D�struct servent * pse;
pse = getservbyname(“ftp”, “tcp”);
printf("ftp port: %d\ n", ntohs(pse-> s_port));
●以下情况下�并发的、面向连接服务器的单线程实现比多线程实现更好的是__(18)__。
(18)�A�每个请求的处理时间很短�均小于 CPU 分片时间
B�各个请求的处理时间很长�均大于 CPU 分片时间
C�服务器运行在具有多个处理器的计算机上
�第 3 页 共 14 页�
B�主进程不关闭从套接字
D�从进程不关闭从套接字
D�各个请求的处理时间变化很大
●以下关于并发的、无连接服务器的叙述中�错误的是__(19)__。
(19)�A�从进程与主进程使用同一个套接字通信
B�并发等级取决于传入请求数
C�并发等级取决于服务的客户数
D�每个传入请求由单独的进程处理
●以下情况下�并发的服务器的多进程实现比多线程实现更好的是__(20)__。
(20)�A�并发执行的服务之间需要访问共享的数据
B�用户需要通过交互方式监控执行服务的状态
C�并发执行的服务之间需要相互通信
D�主服务器需要与执行服务的代码分离
●用多进程实现的并发的、面向连接服务器的进程结构中�主进程无限循环。在每次循
环中�主进程调用 accept 接受传入的连接�并且创建一个从进程处理该连接。在以下
情形下可能导致服务器资源缺乏的是__(21)__。
(21)�A�主进程不关闭主套接字
C�从进程不关闭主套接字
●以下情况下�函数
select(int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval * timeout)
检查描述符后立即返回的是__(22)__。
B�timeout -> tv_sec = = 0 && timeout -> tv_usec = = 0
(22)� A�timeout = = 0
C�timeout = = NULL D�timeout -> tv_sec != 0 | | timeout -> tv_usec != 0
●以下关于多协议�TCP�UDP�服务器的叙述中�错误的是__(23)__。
(23)�A�UDP 服务和 TCP 服务具有相同的计算响应的的代码�但使用不同的协议端口
号�不适合使用多协议服务器
B�UDP 服务和 TCP 服务具有不同的计算响应的代码�但使用相同的协议端口号�
不适合使用多协议服务器
C�多协议服务器的主要优点是消除了代码重复�有助于节约系统资源
D�多协议服务器可以使用一个单线程并发地处理请求�而不管这些请求来自 TCP
还是 UDP
●一个面向连接的、并发的、多服务服务器提供 K 个服务�并发地处理 Q 个请求�它
将使用的套接字的最大数目是__(24)__。
(24)�A�K
●在可动态配置的超级服务器环境中�当要求改变服务器所提供的服务时�__(25)__。
(25)�A�必须重新编译服务器程序并重新启动服务器
B�不必重新编译服务器程序但必须重新启动服务器
C�必须改变配置文件并重新启动服务器
D�只需修改配置文件并通知服务器要求重新配置而不需要重新启动服务器
●相对于需求驱动的并发�从进程/线程预分配的主要优势在于__(26)__。
(26)�A�提高了服务器的并发等级
C�降低了服务器的延迟
●当使用延迟的从进程/线程分配时�服务器一开始循环地处理每个请求。仅对于
__(27)__�服务器才创建一个并发的从进程/线程来处理该请求。
(27)�A�处理时间短的请求
C�含有差错的请求
●以下关于单线程的、面向连接的并发客户实现的说法中�错误的是__ (28)__。
(28)�A�能同时联系多个服务器�而且从任何服务器收到响应就向用户报告
B�减少了对系统资源的持续占用
D�提高了服务器的可靠性
B�处理时间长的请求
D�非授权的请求
D�K+Q+1
C�K+Q
B�K+1
�第 4 页 共 14 页�
B�即使服务器发生故障或死锁�客户仍可能继续读取本地输入和执行控制命令
C�即使客户调用会阻塞的系统调用�也不可能产生死锁
D�客户读取输入或读取来自服务器的响应�是按产生这些数据的速率进行的
●以下服务器并发实现方案最容易引起服务器在不停地处理来自某客户的请求时而剥
夺其它客户的服务的是__(29)__。
(29)�A�循环的、无连接服务器
C�循环的、面向连接服务器
●在客户—服务器环境中�服务器在传输过程中避免阻塞的两种解决办法是�服务器并
发执行�或者__(30)__。
(30)�A�服务器为空闲连接设置计时器
B�服务器在经过固定长时间后关闭连接
C�服务器限制客户所允许发送请求的数目
D�服务器避免会产生阻塞的系统调用
B�多进程并发的、面向连接服务器
D�多线程并发的、面向连接服务器
得
分
【说明】
二、本题中共有 5 个空格�要求全部解答�每个空格 2 分�满分 10 分。阅
读以下说明和C代码�将应填入__(n)__处的字句写在答卷的对应栏内。
源文件 passivesock.c 中定义的函数 passivesock 包含分配套接字的细节�包括使用全
局变量 portbase 将所有端口值都从新映射到更高的范围上�以使测试更加安全。
函数 errexit 使用可变数量的参数�第一个参数指明输出的格式�剩下的参数指明按
所给格式准备要打印的参数。
【源文件 passivesock.c 代码】
/ * passivesock.c - passivesock * /
# include < stdio.h>
# include < sys/ types.h>
# include < sys/ socket.h>
# include < sys/ errno.h>
# include < netinet/ in.h>
# include < netdb.h>
# include < stdarg.h>
# include < string.h>
unsigned short portbase = 0; / * port base, for non-root servers
* /
/ * ------------------------------------------------------------------------------
* passivesock - allocate & bind a server socket using TCP or UDP
* ------------------------------------------------------------------------------
* /
int
passivesock(const char * service, const char * transport, int qlen)
{
struct servent * pse;
struct protoent
* ppe;
�第 5 页 共 14 页�
struct sockaddr_in sin;
int s, type;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = I NADDR_ANY;
if ( __(1)__ )
sin.sin_port = htons(ntohs((unsigned short)pse-> s_port) + portbase);
else if ( __(2)__ )
errexit("can't get \ "%s\ " service entry\ n", service);
if ( (ppe = getprotobyname(transport)) = = 0)
errexit("can't get \ "%s\ " protocol entry\ n", transport);
if ( __(3)__ )
type = SOCK_DGRAM;
else
type = SOCK_STREAM;
s = socket(PF_I NET, type, ppe-> p_proto);
if (s < 0)
errexit("can't create socket: %s\ n", strerror(errno));
if ( __(4)__ )
errexit("can't bind to %s port: %s\ n", service, strerror(errno));
if ( __(5)__ )
errexit("can't listen on %s port: %s\ n", service, strerror(errno));
return s;
}
/ * ------------------------------------------------------------------------
* errexit - print an error message and exit
* ------------------------------------------------------------------------
* /
int
errexit(const char * format, ...)
{
va_list
args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
exit(1);
}
�第 6 页 共 14 页�
得
分
【说明】
三、本题中共有 5 个空格�要求全部解答�每个空格 2 分�满分 10 分。阅
读以下说明和C代码�将应填入__(n)__处的字句写在答卷的对应栏内。
源文件 TCPmtechod.c 含有 ECHO 服务的单进程服务器代码。
程序中调用第二题程序 passivesock.c 中定义的函数 passivesock 创建被动的套接字。
调用函数 errexit 输出出错信息并退出�输出的格式遵循 printf 的约定。
【源文件 TCPmtechod.c 代码】
/ * TCPmtechod.c - main, TCPechod * /
# include < stdio.h>
# include < pthread.h>
# include < sys/ errno.h>
# include < netinet/ in.h>
# def ine
QLEN
# def ine
BUFSIZE
32
4096
int
int
int
TCPechod(int fd);
errexit(const char * format, ...);
passivesock(const char * service, const char * transport, int qlen);
/ * ------------------------------------------------------------------------
* main - Concurrent TCP server for ECHO service
* ------------------------------------------------------------------------
* /
int
main(int argc, char * argv[ ] )
{
pthread_t
th;
pthread_attr_t
ta;
const char
* service = "echo";
const char
* transport = "tcp";
struct
sockaddr_in fsin;
unsigned int alen;
int msock;
int ssock;
switch (argc) {
case 1:
break;
case 2:
service = argv[ 1] ;
break;
default:
�第 7 页 共 14 页�
}
errexit("usage: TCPechod [ port] \ n");
msock = passivesock(service, transport, QLEN);
(void) pthread_attr_init(&ta);
(void) pthread_attr_setdetachstate(&ta, PTHREAD_CREATE_DETACHED);
while (1) {
alen = sizeof(fsin);
ssock = __(1)__ ;
if (ssock < 0) {
if (errno = = EINTR)
__(2)__ ;
errexit("accept: %s\ n", strerror(errno));
}
if (pthread_create( __(3)__ ) < 0)
errexit("pthread_create: %s\ n", strerror(errno));
}
}
/ * ------------------------------------------------------------------------
* TCPechod - echo data until end of f ile
* ------------------------------------------------------------------------
* /
int
TCPechod(int fd)
{
char buf[ BUFSI Z] ;
int cc;
while ( __(4)__ ) {
if (cc < 0)
errexit("echo read: %s\ n", strerror(errno));
if ( __(5)__ )
errexit("echo write: %s\ n", strerror(errno));
}
(void) close(fd);
return 0;
}
�第 8 页 共 14 页�