网络应用编程习题解答合并版.docx
《网络应用编程习题解答合并版.docx》由会员分享,可在线阅读,更多相关《网络应用编程习题解答合并版.docx(30页珍藏版)》请在冰豆网上搜索。
网络应用编程习题解答合并版
网络应用编程
习题解答
课程名称
网络应用编程
院(部)
计算机与信息工程学院
教研室(实验室)
网络工程教研室
主讲教师
侯彦娥
职称
讲师
使用教材
21世纪高等学校计算机规划教材(精品系列)《C#网络应用编程(第2版)》,马骏等主编,人民邮电出版社
第1章习题解答
1.简要回答什么是分散式、集中式和分布式通信模型。
【解答】
分散式指用户只负责管理自己的计算机系统,各自独立的系统之间没有资源或信息的交换或共享。
集中式指用一台主计算机保存一个企业组织的全部数据,而用户则通过终端连接到这台主计算机系统并与之通信,从而达到访问数据的目的。
终端是包含键盘和显示器的端设备,通过通信链路发送和接收数据。
分布式是分散式系统和集中式系统的混合,它由一个又一个连接起来的独立计算机组成。
企业管理系统就是集中式和分布式综合的一种表现,所有数据用专用的数据库(SQLServer、Oracle或者DB2)集中存储,属于集中式,而对数据的处理则由各个部门的软件分别控制,属于分布式。
2.TCP/IP四层模型中各层的主要功能是什么?
【解答】
TCP/IP参考模型采用4层的层级结构,每一层都呼叫它的下一层所提供的网络来完成自己的需求。
这4层分别为:
应用层、传输层、网际层和网络接口层。
应用层负责应用程序之间的沟通。
传输层提供节点间的数据传送以及应用程序之间的通信服务,主要功能是数据格式化、数据确认和丢失重传等。
网际层负责提供基本的数据封包传送功能,让每一块数据包都能够到达目的主机,但它不检查数据包是否被正确接收。
网络接口层负责接收IP数据报并进行传输,从网络上接收物理帧,抽取IP数据报转交给下一层,对实际的网络媒体进行管理,定义如何使用实际网络(如Ethernet、SerialLine等)来传送数据。
第2章习题解答
1)进程和线程有什么区别?
1)一个完整的进程拥有自己独立的内存空间和数据,但是同一个进程内的线程是共享内存空间和数据的。
一个进程对应着一段程序,它是由一些在同一个程序里面独立的同时运行的线程组成的。
线程有时也被称为并行运行在程序里的轻量级进程,这是因为它的运行依赖于进程提供的上下文环境,并且使用的是进程的资源。
在一个进程里,线程的调度有抢占式或者非抢占的模式。
在抢占模式下,操作系统负责分配CPU时间给各个线程,一旦当前的线程使用完分配给自己的CPU时间,操作系统将决定下一个占用CPU时间的是哪一个线程。
因此操作系统将定期的中断当前正在执行的线程,将CPU分配给在等待队列的下一个线程。
所以任何一个线程都不能独占CPU。
每个线程占用CPU的时间取决于进程和操作系统。
进程分配给每个线程的时间很短,以至于我们感觉所有的线程是同时执行的。
2)线程是如何创建的?
怎样设置线程的优先级?
C#中创建线程的工作是通过使用System.Threading名称空间下的Thread类的构造方法来完成的,如创建一个线程实例输出字符“a”1000次。
Threadthread=newThread(newThreadStart(func1));
thread.Priority=ThreadPriority.Normal;
thread.Start();
staticvoidfunc1()
{
for(inti=0;i<1000;i++)
{
Console.WriteLine("a");
}
}
C#中System.Threading名称空间下的ThreadPriority枚举类定义了线程可能具有的所有优先级的值,优先级由高到低排序为:
Highest,AboveNormal,Normal,BelowNormal,Lowest。
可以通过访问线程的Priority属性来获取和设置其优先级。
每个线程都具有分配给它的线程优先级。
在公共语言运行库中创建的线程最初分配的优先级为ThreadPriority.Normal。
在运行库以外创建的线程保留它们在进入托管环境之前具有的优先级。
可以使用Thread.Priority属性获取或设置任何线程的优先级。
3)前台线程和后台线程有什么区别?
如何将一个线程设置为后台线程?
3)前台线程和后台线程的区别是后台线程不会影响进程终止。
属于某个进程的所有前台线程都终止后,公共语言运行库就会结束该进程,而且所有属于该进程的后台线程也都会立即停止,而不管后台工作是否完成。
利用Thread对象的IsBackground属性,可以设置或判断一个线程是后台线程还是前台线程。
在任何时候,都可以通过将某个线程的IsBackground属性设置为true,使其变为后台线程。
2.为什么要用多线程?
多线程适用于哪种场合?
【解答】
在Client/Server模式下,服务器需要不断监听来自多个客户端的请求,这时,如果采用单线程机制的话,这个线程由于要不断的循环监听客户端请求,从而无暇处理其他的任务。
要让服务器同时为多个客户服务,必须引入多线程技术。
实际上,当执行需要较长时间才能完成的连续操作时,或者等待网络或其他I/O设备响应时,都可以使用多线程技术。
多线程特别适用于需要不同资源(如文件句柄和网络连接)的任务。
3.什么是线程同步?
为什么需要使用线程同步?
C#提供了什么语句可以简单地实现线程的同步?
【解答】
多个线程同时运行时,可能会因为线程之间的逻辑关系而而决定最先执行,谁后执行。
这就是线程同步。
同步是多线程中一个非常重要的概念。
所谓同步,是指多个线程之间存在先后执行顺序的关联关系。
使用多线程可以解决了吞吐量和响应速度的问题,但同时也带来了资源共享问题,如死锁和资源争用。
如果一个线程必须在另一个线程完成某个工作后才能继续执行,则必须考虑如何让其保持同步,以确保在系统上同时运行多个线程而不会出现死锁或逻辑错误。
当两个线程t1和t2有相同的优先级,并且同时在系统上运行时,如果先把时间片分给t1使用,它在变量variable1中写入某个值,但如果在时间片用完时它仍没有完成写入,这时由于时间片已经分给t2使用,而t2又恰好要尝试读取该变量的值,此时读出的就不是正确的值。
这种情况下,如果使用同步仅允许一个线程使用variable1,在该线程完成对variable1的写入工作后再让t2读取这个值,就可以避免出现此类错误。
C#提供了lock语句来实现线程的同步。
4.什么是线程池?
使用线程池有什么好处?
【解答】
线程池是在后台执行多个任务的线程集合。
使用线程池接受传入的请求,每个传入请求都分配给线程池中的一个线程,从而达到异步处理请求的目的。
在服务器应用程序中,如果每到一个请求就创建一个新线程,然后在新线程中为其请求服务的话,将不可避免的造成系统开销的增大。
实际上,创建太多的线程可能会导致由于过度使用系统资源而耗尽内存。
为了防止资源不足,服务器应用程序可以采用线程池来限制同一时刻处理的线程数目。
线程池不会占用主线程,也不会延迟后续请求的处理。
一旦池中的某个线程完成任务,它将返回到等待线程队列中,等待被再次使用。
这种重用使应用程序可以避免为每个任务创建新线程引起的资源和时间消耗。
第3章习题解答
1、使用DNS类和IPHostEntry类创建一个如图3-6所示的域名解析器。
用户输入主机名或者DNS域名以后,能在下面的列表框中显示与主机或者DNS域名对应的IP地址和别名。
图3-6设计界面
【解答】
1)主要源程序如下:
usingSystem.Net;
privatevoidbutton1_Click(objectsender,EventArgse)
{
try
{
this.Cursor=Cursors.WaitCursor;
//解析主机名
IPHostEntryIPinfo=Dns.GetHostEntry(textBox1.Text);
//清空列表框
listBox1.Items.Clear();
listBox2.Items.Clear();
//显示IP地址
foreach(IPAddressIPinIPinfo.AddressList)
{
listBox1.Items.Add(IP.ToString());
}
//显示别名
foreach(stringaliasinIPinfo.Aliases)
{
listBox2.Items.Add(alias);
}
//显示主机名
textBox2.Text=IPinfo.HostName;
}
catch(Exceptionex)
{
MessageBox.Show(ex.Message);
}
finally
{
this.Cursor=Cursors.Default;
}
}
2、参考例3-3的运行界面,编写程序实现获取本机TCP连接统计信息。
【解答】
1)主要源程序如下:
privatevoidFormIPGlobalStatistics_Load(objectsender,EventArgse)
{
IPGlobalPropertiesproperties=IPGlobalProperties.GetIPGlobalProperties();
TcpConnectionInformation[]connections=properties.GetActiveTcpConnections();
foreach(TcpConnectionInformationtinconnections)
{
listBoxResult.Items.Add("Localendpoint:
"+t.LocalEndPoint.Address);
listBoxResult.Items.Add("Remoteendpoint:
"+t.RemoteEndPoint.Address);
listBoxResult.Items.Add("State:
"+t.State);
}
}
2)运行结果如图3-7所示。
图3-7设计界面
3、什么是编码?
什么是解码?
为什么要对字符进行编码和解码?
.NET框架提供了哪些用于字符编码和解码的类?
【解答】
在网络通信中,很多情况下通信双方传达的都是字符信息。
但是,字符信息并不能直接从网络的一端传递到另一端,这些字符信息首先需要被转换成一个字节序列后才能在网络中传输,将字符序列转换为字节序列的过程称为编码。
当这些字节传送到网络的接收方时,接收方需反过来将字节序列再转换为字符序列,这种过程称为解码。
NETFramework提供了哪些用于字符编码和解码的类有Encoding、Encoder、Decoder。
Encoding类位于System.Text命名空间中,主要用于在不同的编码和Unicode之间进行转换。
在网络传输和文件操作中,如果数据量比较大,需要划分为较小的块,此时可能出现一个数据块的末尾是一个不匹配的高代理项,而与其匹配的低代理项则位于下一个数据块中。
对于这种情况,直接使用Encoding类的GetBytes方法编写程序就比较麻烦。
此时,可以利用Encoder类及Decoder类轻松地解决这个问题。
4、参考例3-5的运行界面,编写程序利用Encoding类实现编码及解码。
【解答】
usingSystem;
usingSystem.Collections.Generic;
usingSystem.ComponentModel;
usingSystem.Data;
usingSystem.Drawing;
usingSystem.Text;
usingSystem.Windows.Forms;
usingSystem.Net.NetworkInformation;
namespaceEncoderDecoderExample
{
publicpartialclassFormEncoderDecoder:
Form
{
publicFormEncoderDecoder()
{
InitializeComponent();
}
privatevoidbuttonRun_Click(objectsender,EventArgse)
{
//编码
StringstrCodeType=boBoxType.SelectedItem.ToString();
Encodingencoder=Encoding.GetEncoding(strCodeType);
Byte[]bytes=encoder.GetBytes(this.textBoxOldText.Text);
textBoxEncoder.Text=Convert.ToBase64String(bytes);
//解码
Encodingdecoder=Encoding.GetEncoding(strCodeType);
stringstrResult=decoder.GetString(bytes);
textBoxDecoder.Text=strResult;
}
privatevoidFormEncoderDecoder_Load(objectsender,EventArgse)
{
//显示现有的编码类型
foreach(EncodingInfoeiinEncoding.GetEncodings())
{
Encodingen=ei.GetEncoding();
boBoxType.Items.Add(en.HeaderName);
}
boBoxType.SelectedIndex=0;
}
}
}
第4章习题解答
1、什么是套接字?
套接字有哪几种不同的类型?
【解答】
套接字是引用网络连接的特殊的文件描述符,它有三个基本要素组成:
网络类型、数据传输类型、采用的网络协议。
Socket类的构造函数为:
Socket(AddressFamilyaf,SocketTypest,ProtocolTypept)
其中,AddressFamily为网络类型,SocketType为数据类型,ProtocolTyp为使用的网络协议。
Socket构造函数的三个参数中,对于网络上的IP通信来说,AddressFamily总是使用AddressFamily.InterNetwork枚举值。
SocketType参数则与ProtocolType参数配合使用,不允许其它的匹配形式,也不允许混淆匹配。
2、说明面向连接套接字服务端编程的基本步骤。
【解答】
1)创建一个包含采用的网络类型、数据传输类型和协议类型的本地套接字对象,并将其与服务器的IP地址和端口号绑定。
这个过程可以通过Socket类。
2)在指定的端口进行监听,以便接受客户端连接请求。
3)一旦接受了客户端的连接请求,就根据客户端发送的连接信息创建与该客户端对应的Socket对象。
4)根据创建的Socket对象,分别与每个连接的客户进行数据传输。
5)根据传送信息情况确定是否关闭与对方的连接。
3、.NET提供的从Stream继承的数据流类都有那些?
【解答】
文件流:
FileStream
内存流:
MemoryStream
加密流:
CryptoStream
4、什么是网络流?
网络流的基本操作有哪些?
【解答】
可以将NetworkStream看作在数据来源端和接收端之间架设了一个数据通道,这样一来,读取和写入数据就可以针对这个通道来进行。
NetworkStream流具有读取和写入两个基本操作。
对于NetworkStream流,写入操作是指从来源端内存缓冲区到网络上的数据传输;读取操作是从网络上到接收端内存缓冲区(如字节数组)的数据传输。
网络流不具有查找操作。
5、利用StreamWriter与StreamReader类读写流具有什么样的优势?
【解答】
NetworkStream、MemoryStream和FileStream类都提供了以字节为基本单位的读写方法,但是这种方法需要首先将待写入的数据转化为字节序列后才能进行读写,当操作的是使用字符编码的文本数据时,使用很不方便。
因此,在操作文本数据时,一般使用StreamWriter、StreamReader执行这些功能。
第5章习题解答
1.TCP有哪些主要特点?
【解答】
TCP最主要的特点是:
(1)是面向连接的传输层协议;
(2)每个TCP连接只能有两个端点,而且只能一对一通信,不能一点对多点直接通信;
(3)通过TCP连接传送的数据,能保证数据无差错、不丢失、不重复地准确到达接收方,并且保证各数据到达的顺序与数据发出的顺序相同;
(4)数据以字节流的方式传输;
(5)传输的数据无消息边界。
2.简要回答编写基于TCP的服务器端和客户端程序的一般步骤。
【解答】
使用对套接字封装后的类,编写基于TCP的服务器端程序的一般步骤为:
(1)创建一个TcpListener对象,然后调用该对象的Start方法在指定的端口进行监听。
(2)在单独的线程中,循环调用AcceptTcpClient方法接受客户端的连接请求,并根据该方法的返回的结果得到与该客户端对应的TcpClient对象。
(3)每得到一个新的TcpClient对象,就创建一个与该客户对应的线程,在线程中与对应的客户进行通信。
(4)根据传送信息的情况确定是否关闭与客户的连接。
使用对套接字封装后的类,编写基于TCP的客户端程序的一般步骤如下:
(1)利用TcpClient的构造函数创建一个TcpClient对象。
(2)使用Connect方法与服务器建立连接。
(3)利用TcpClient对象的GetStream方法得到网络流,然后利用该网络流与服务器进行数据传输。
(4)创建一个线程监听指定的端口,循环接收并处理服务器发送过来的信息。
(5)完成工作后,向服务器发送关闭信息,并关闭与服务器的连接。
3.解决TCP的无消息边界问题有哪些常用的方法?
【解答】
常用的方法有三种:
(1)发送固定长度的消息。
适用于信息长度固定的场合。
(2)将消息长度与消息一起发送。
此方法适用于任何场合。
(3)使用特殊标记分隔消息。
适用于消息本身不包含特殊标记的场合。
4.简述异步编程的两种模式。
【解答】
(1)基于事件的异步设计模式
该模式用事件驱动模型实现异步方法。
这种模式用单独的线程在后台执行耗时的任务,当后台任务完成时,就自动触发对应的事件。
该模式既具有多线程应用程序的优点,同时也隐匿了多线程设计中固有的许多复杂问题。
(2)基于IAsyncResult的异步设计模式
基于IAsyncResult的异步设计模式通过前缀分别为“Begin”和“End”的两个方法实现开始和结束异步操作,每个Begin方法都必须有一个与其对应的End方法。
程序在调用Begin方法后,调用该方法的线程会继续执行其下面的语句,同时该方法用另一个单独的线程执行异步操作,当异步操作完成后,会返回一个实现IAsyncResult接口的对象,循环判断该对象的IsCompleted属性,来决定异步操作是否完成。
调用Begin方法后,程序调用End方法来结束异步操作。
编写一般异步操作的应用程序时,建议尽量使用基于事件的异步设计模式,因为它能有效地提高项目开发效率和质量,同时也降低了异步编程的复杂度。
5.如果要在服务器进行监听的同时进行其他操作,异步套接字需要提供那些方法?
【解答】
异步套接字需要提供那些方法:
(1)需要开始接受网络连接请求的方法
(2)需要一个处理连接请求并开始发送或接收网络数据的回调方法
(3)需要一个结束发送或接收数据的方法
6.简述利用轮询方式的异步设计模式控制同步方法的实现思路。
【解答】
.NETFramework提供了一种可以利用委托异步调用任何方法的技术。
实现思路:
首先,声明一个与要调用的方法具有相同签名的委托,声明后,公共语言运行时就会自动为该委托定义BeginInvoke方法和EndInvoke方法。
然后,调用BeginInvoke方法开始异步执行,该方法会立即返回IasyncResult类型的接口,从用户界面的服务线程中进行异步调用时,可以利用该接口的IsCompleted属性来通过轮询方式检查异步调用是否完成。
在轮询过程中,BeginInvoke方法在ThreadPool中创建的线程会继续执行异步方法。
程序调用BeginInvoke后,会继续执行BeginInvoke方法后面的代码,而不是等待异步调用完成。
最后,调用委托的EndInvoke方法结束异步操作。
如果异步调用尚未完成,则EndInvoke会一直阻止调用线程,直到异步调用完成。
由于有可能会引起调用EndInvoke方法的线程阻塞,所以一般不要从服务于用户界面的线程直接调用该方法,否则会在异步操作完成前,给用户一个界面无反应的错觉。
为了使界面操作流畅,可以将上面的语句改为用其他线程执行。
第6章习题解答
1、UDP协议和TCP协议的主要区别有哪些?
【解答】
UDP是一个简单的、面向数据报的无连接协议,提供了快速但不一定可靠的传输服务。
与TCP一样,UDP也是构建于底层IP协议之上的传输层协议。
与TCP相比,UDP有如下一些特点:
首先,UDP协议是基于无连接的协议,它能够消除生成连接的系统延迟,所以速度比TCP更快。
对于强调传输性能而不是传输完整性的应用(例如音频和多媒体应用)UDP是最好的选择。
其次,UDP不但支持一对一连接,而且也支持一对多连接,可以使用广播的方式多地址发送,而TCP仅支持一对一通信;第三,UDP与TCP的报头比是8:
20,这使得UDP消耗的网络带宽更少。
最后,UDP协议传输的数据有消息边界,而TCP协议没有消息边界。
但是使用UDP协议的发送无法了解数据报是否已经到达终端系统,这样一来,UDP就无法保证数据被真正传送到了目标。
UDP没有任何对双方会话的支持,也不保证各数据报到达的顺序与数据包发出的顺序相同,可靠性不如TCP协议。
2、UdpClient的Connect方法和TcpClient的Connect方法语法形式基本一致,作用是否相同?
【解答】
不同。
UdpClient的Connect方法仅指定远程主机,并不向远程主机发送连接请求。
TcpClient的Connect方法向远程主机发送连接请求。
3、对于网络地址192.168.1.0,使用子网掩码255.255.255.0,写出网络地址192.168.1.0的本地广播地址。
【解答】
广播地址为:
192.168.1.255
4、什么是广播、组播?
两者有什么区别?
【解答】
所谓广播,就是指同时向多个设备发送消息,并且所有子网中的设备都可以接收到发送方发来的消息。
每个广播消息包含一个特殊的IP地址。
广播消息地址分为两种类型:
本地广播和全球广播。
本地广播可以向子网中的所有设备发送广播消息,其他网络不会受到本地广播的影响。
全球广播使用四个字节所有位全为1的IP地址,即点分十进制的255.255.255.255,这个特定的广播地址表明数据包的目的地是网络上的所有设备。
但是由于路由器会自动过