《计算机网络编程》复习题.docx
《《计算机网络编程》复习题.docx》由会员分享,可在线阅读,更多相关《《计算机网络编程》复习题.docx(21页珍藏版)》请在冰豆网上搜索。
《计算机网络编程》复习题
1.基本概念
1.1.什么是协议
计算机通信网络中两台计算机之间进行通信所必须共同遵守的规定或规则。
1.2.TCP/IP协议的四层体系结构
应用层(Telnet、FTP、HTTP、DNS、SNMP、SMTP)
传输层(TCP、UDP)
网络层(IP、ICMP、IGMP)
链路层(以太网、令牌环网、FDDI、IEEE802.3)
1.3.IP地址的结构、分类、多播(或称组播)
目前使用的IP协议为ipv4(即IP协议的第四版),使用32位二进制表示
结构:
网络号
主机号
分类:
A,B,C,D,E等五类地址,见下表
类别
类标识
地址范围
第一字节
网络地址长度
最大网络数
最大主机数
选用范围
A类
0
1~126
1字节
126
16777214
大型网络
B类
10
128~191
2字节
16382
65534
中型网络
C类
110
192~223
3字节
2097150
254
小型网络
D类
1110
224.0.0.0~239.255.255.255
224~239
多点播送
E类
11110
240~247
保留地址
直接广播地址:
主机号为全1的IP地址;
多播:
1)一对多的通信,一个源点发送到多个终点;
2)标识一个多播的标识符即为一个D类地址;
3)使用IGMP(网际组管理协议)协议,首部的协议字段值为2
4)多播地址只能用于目的地址,不能用于源地址;
5)对多播数据报不产生ICMP差错报文;
多播分两种:
局域网范围的硬件多播;因特网范围的多播,因为大部分主机是通过局域网接入到因特网的,因此在多播的最后阶段,还是要在局域网范围内进行硬件多播。
1.4.多播(或称组播)IP地址,如何映射到MAC地址
组播IP地址,即D类地址,范围是224.0.0.0~239.255.255.255;
MAC地址的前25位是固定的,后23位与IP地址的后23位相同
IP地址
1110yyyy
yxxxxxxx
xxxxxxxx
xxxxxxxx
MAC地址
00000001
00000000
01011110
0xxxxxxx
xxxxxxxx
xxxxxxxx
(16进制)
01
00
5e
1.5.标识网络中的两个通信的进程或一条连接
五元组(协议,本地IP地址,本地端口号,远程IP地址,远程端口号)
1.6.socket(套接字)的三种协议类型及其应用场合
socket(intaf,inttype,intprotocol)函数中,当第二个参数为AF_INET时,第三个参数type的值可以为:
SOCK_STREAM(流式套接字)、SOCK_DGRAM(数据报套接字)、SOCK_RAW(原始套接字),详情见下表:
协议类型
应用场合
socket函数中的protocol值
SOCK_STREAM
TCP
IPPROTO_TCP
SOCK_DGRAM
UDP
IPPROTO_UDP
SOCK_RAW
rawsockets
IPPROTO_ICMP
1.7.写代码:
创建socket
1)TCP
SOCKETtcpSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
2)UDP
SOCKETudpSocket=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
3)原始套接字
SOCKETicmpSocket=socket(AF_INET,SOCK_RAM,IPPROTO_ICMP);
1.8.TCP的C/S通信模型
1.9.UDP的C/S通信模型
1.10.服务器端的两种绑定方式的区别
IP地址
端口参数
方式1
INADDR_ANY
非0值
所有网卡都可接收连接,所有人都可连接
方式2
IP地址
非0值
某网卡接收,指定人群连接
函数bind原型为:
intbind(SOCKETs,conststructsockaddr*name,intnamelen)
代码如下:
SOCKETlistenSocket;
structsockaddr_inservice;
listenSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
//绑定方式1:
service.sin_port=htons(9999);
service.sin_addr.s_addr=inet_addr(INADDR_ANY);
//绑定方式2:
service.sin_port=htons(9999);
service.sin_addr.s_addr=inet_addr("127.0.0.1");
bind(listenSocket,(SOCKADDR*)&service,sizeof(service));
1.11.函数listen中第二个参数的含义
函数原型为:
intlisten(SOCKETs,intbacklog);
第二个参数backlog:
设置等待连接队列的最大长度,若设置为SOMAXCONN,则表示可用的最大长度。
1.12.在网络通信中,怎样传输一个字符串(可能含有汉字)
统一字符编码为UTF-8,传输时,先传输字符串的长度,再传输字符串内容。
2.程序设计
2.1.写代码:
两个线程,交替打印数字
步骤:
WSAStartup(),初始化winsock
socket(),创建TCP型的socket
bind(),绑定服务器的IP、PORT
listen(),监听socket
while(continue){
accept(),接收客户端的连接
创建新线程,传入通信用的socket,与客户端进行通信
}
closesocket(),关闭socket
WSACleanup(),释放winsock资源
代码:
/**
*main.cpp
*多线程程序
*两个线程,分别打印线程号+数字
*/
#include
#include
#include
unsignedintCALLBACKmyThread(void*p);
intmain(){
HANDLEhandles[2];
handles[0]=(HANDLE)_beginthreadex(NULL,0,myThread,NULL,0,NULL);
handles[1]=(HANDLE)_beginthreadex(NULL,0,myThread,NULL,0,NULL);
WaitForMultipleObjects(2,handles,true,INFINITE);
CloseHandle(handles[0]);
CloseHandle(handles[1]);
return0;
}
unsignedintCALLBACKmyThread(void*p)
{
for(inti=1;i<=10;i++)
{
printf("Thread:
%u打印:
%d\n",GetCurrentThreadId(),i);
Sleep(2000);
}
return0;
}
程序截图:
2.2.程序设计步骤:
多线程TCP服务器端程序
步骤:
WSAStartup(),初始化winsock
socket(),创建TCP型的socket
bind(),绑定服务器的IP、PORT
listen(),监听socket
while(continue){
accept(),接收客户端的连接
创建新线程,传入通信用的socket,与客户端进行通信
}
closesocket(),关闭socket
WSACleanup(),释放winsock资源
代码:
/**
*多线程TCP服务器端程序
*/
#include
#include
#include
#pragmacomment(lib,"ws2_32")
//线程:
处理一个客户机的网络通信。
unsignedintCALLBACKtcpThread(void*p);
intmain(){
intiResult;
WORDwVersionRequested;
WSADATAwsaData;
SOCKETlistenSocket;
SOCKETacceptSocket;
structsockaddr_inservice;
HANDLEhandles[10];
wVersionRequested=MAKEWORD(2,2);
/*InitializingWinsock*/
iResult=WSAStartup(wVersionRequested,&wsaData);
if(iResult!
=0){
printf("WSAStartupfailedwitherror:
%d\n",iResult);
return-1;
}
/*createatcpsocket*/
listenSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(listenSocket==INVALID_SOCKET){
printf("createsocketfaliedwitherror:
%d\n",WSAGetLastError());
WSACleanup();
return-1;
}
/*bindthesocket*/
service.sin_family=AF_INET;
service.sin_port=htons(9999);
service.sin_addr.s_addr=inet_addr("127.0.0.1");
iResult=bind(listenSocket,(SOCKADDR*)&service,sizeof(service));
if(iResult==SOCKET_ERROR){
printf("bindfailedwitherror:
%d\n",WSAGetLastError());
closesocket(listenSocket);
WSACleanup();
return-1;
}
/*listenforincomingconnectionrequests*/
iResult=listen(listenSocket,SOMAXCONN);
if(iResult==SOCKET_ERROR){
printf("listenfailedwitherror:
%d\n",WSAGetLastError());
closesocket(listenSocket);
WSACleanup();
return-1;
}
printf("listeningonsocket...\n");
/*acceptnewincomingconnections*/
intagain=0;
while(again<10){
structsockaddr_inclient_addr;
intclient_addr_size=sizeof(client_addr);
SOCKETclientSock=accept(listenSocket,(structsockaddr*)&client_addr,&client_addr_size);
if(clientSock!
=INVALID_SOCKET){
closesocket(listenSocket);
WSACleanup();
return-1;
}
handles[again]=(HANDLE)_beginthreadex(NULL,0,tcpThread,(void*)clientSock,0,NULL);
again++;
}
WaitForMultipleObjects(10,handles,TRUE,INFINITE);
for(inti=0;i<10;i++){
CloseHandle(handles[i]);
}
closesocket(listenSocket);
WSACleanup();
return0;
}
//线程:
处理一个客户机的网络通信。
unsignedintCALLBACKtcpThread(void*p){
SOCKETclient=(SOCKET)p;
/*dosomething:
*recv()/send()
*/
return0;
}
2.3.程序设计步骤:
UDP多循环服务器程序
步骤:
WSAStartup(),初始化winsock
socket(),创建UDP型的socket
bind(),绑定服务器的IP、PORT
while(continue){
recvfrom(),接收UDP包
sendto(),发送UDP包
}
closesocket(),关闭socket
WSACleanup(),释放winsock资源
代码:
/**
*UDPServer
*/
#include
#include
#pragmacomment(lib,"ws2_32")
intmain(){
WSADatawsaData;
WORDwVersionRequested;
intiResult;
structsockaddr_inservice;
SOCKETlistenSocket;
wVersionRequested=MAKEWORD(2,2);
iResult=WSAStartup(wVersionRequested,&wsaData);
if(iResult!
=0){
printf("WSAStartupfailedwitherror:
%d\n",iResult);
return-1;
}
listenSocket=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
if(listenSocket==INVALID_SOCKET){
printf("createsocketfailedwitherror:
%d\n",WSAGetLastError());
WSACleanup();
}
service.sin_family=AF_INET;
service.sin_addr.s_addr=inet_addr("127.0.0.1");
service.sin_port=htons(9999);
iResult=bind(listenSocket,(SOCKADDR*)&service,sizeof(service));
if(iResult==SOCKET_ERROR){
printf("bindfailedwitherror:
%d\n",WSAGetLastError());
closesocket(listenSocket);
WSACleanup();
return-1;
}
structsockaddr_inclient_addr;
intlen=sizeof(client_addr);
while
(1){
/*dosomething:
*recvfrom()
*sendto()
*/
}
closesocket(listenSocket);
WSACleanup();
return0;
}
2.4.连接型UDP一般用于哪一方?
什么场合?
一般用于客户端;
要求内核进行UDP包的过滤;
2.5.广播程序,每隔3秒广播本地时间
步骤:
WSAStartup(),初始化winsock
socket(),创建socket
setsockopt(),允许广播
while(continue){
getCurrentTime(),获取本地时间
sendto(),发送数据
Sleep(),暂停3秒
}
closesocket(),关闭socket
WSACleanup(),释放winsock资源
代码:
/**
*广播服务器端程序
*每3秒广播服务器端的时间
*/
#include
#include
#include
#pragmacomment(lib,"ws2_32")
voidgetcurtime(char*curtime){
time_ttm;//time.h
time(&tm);//time.h
sprintf(curtime,"%s\n",ctime(&tm));
}
intmain(){
intiResult;
WORDwVersionRequested;
WSADATAwsaData;
SOCKETserverSocket;
structsockaddr_inservice;
charon=1;
charmsg[256];
serverSocket=socket(AF_INET,SOCK_DGRAM,0);
setsockopt(serverSocket,SOL_SOCKET,SO_BROADCAST,&on,sizeof(on));//允许发广播包
service.sin_family=AF_INET;
service.sin_port=htons(9999);
service.sin_addr.s_addr=htonl(INADDR_BROADCAST);
while
(1){
getcurtime(msg);
sendto(serverSocket,msg,strlen(msg),0,(sockaddr*)&serverSocket,sizeof(serverSocket));
printf("%s\n",msg);
Sleep(3000);/*sleep3secondsbetweensend*/
}
closesocket(serverSocket);
WSACleanup();
return0;
}
2.6.多播(或称组播)程序,每隔3秒多播本地时间
步骤:
WSAStartup(),初始化winsock
socket(),创建socket
setsockopt(),允许广播
while(continue){
getCurrentTime(),获取本地时间
sendto(),发送数据到某D类地址
Sleep(),暂停3秒
}
closesocket(),关闭socket
WSACleanup(),释放winsock资源
代码:
/**
*多播服务器端程序
*每3秒广播服务器端的时间
*/
#include
#include
#include
#pragmacomment(lib,"ws2_32")
voidgetcurtime(char*curtime){
time_ttm;//time.h
time(&tm);//time.h
sprintf(curtime,"%s\n",ctime(&tm));
}
intmain(){
intiResult;
WORDwVersionRequested;
WSADATAwsaData;
SOCKETserverSocket;
structsockaddr_inservice;
charon=1;
charmsg[256];
serverSocket=socket(AF_INET,SOCK_DGRAM,0);
setsockopt(serverSocket,SOL_SOCKET,SO_BROADCAST,&on,sizeof(on));//允许发广播包
service.sin_family=AF_INET;
service.sin_port=htons(9999);
service.sin_addr.s_addr=inet_addr("226.6.6.6");
printf("每3秒向组226.6.6.6发包,告之本机的时间\n");
while
(1){
getcurtime(msg);
sendto(serverSocket,msg,strlen(msg),0,(sockaddr*)&serverSocket,sizeof(serverSocket));
printf("%s\n",msg);
Sleep(3000);/*sleep3secondsbetweensend*/
}
closesocket(serverSocket);
WSACleanup();
return0;
}
3.协议分析
3.1.IP数据报头部最大/小长度、头部选项最大/小长度,最多记录路由个数
头部最小长度:
20Bytes
头部最大长度:
60Bytes
选项最小长度:
0Bytes
选项最小长度:
40Bytes
最多记录路由:
9个
3.2.程序设计步骤:
MyPing
(源主机发送类型为8代码为0的“回送请求报文”,当目标主机收到该报文时,将标识符、序号、数据区复制以组成类型为0代码为0的“回送应答报文”,发送给源主机。
)
1)创建原始套接字;
2)设置套接字的超时选项(如6秒);
3)构造ICMP数据报:
类型为8代码为0回送请求;
4)构造IP数据报,将上述的ICMP数据报作为IP数据报的数据部分;设置超时选项;
5)发送IP数据报到目标IP地址、端口;
6)若收