TCPIP协议分析实验指导书.doc_第1页
TCPIP协议分析实验指导书.doc_第2页
TCPIP协议分析实验指导书.doc_第3页
TCPIP协议分析实验指导书.doc_第4页
TCPIP协议分析实验指导书.doc_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

TCP/IP协议分析课程实验指导书实验1 TCP套接字编程实验实验目的:熟悉基于java的TCP套接字网络编程方法;熟悉TCP Client套接字编程流程;熟悉TCP Server套接字编程流程;熟悉 java TCP套接字编程涉及的java类;实验任务:实现一个基本的TCP套接字Client/Server模式的网络应用系统,该系统中服务器端监听网络,接受客户端的连接请求,并接收客户端发送的数据,并原封部分的发回给客户端。即实现一个类似于Echo服务的服务器程序。指导说明:1. TCP客户端基本编程流程1.1 TCP客户端工作流程1. 创建流套接字向远程服务器发起连接请求;2. 获取套接字字节流与远程服务器进行数据通信;3. 通信完毕,关闭套接字;1.2 基于Java 的TCP客户端编写基本步骤说明基于Java的TCP客户端会使用下述类或接口:Socket、InetAddress、InputStream、OutPutStream等,基本上这些可能在Java TCP客户端程序中使用的类大致会包含于下述常用的Java库文件中:.*、java.io.*、java.util.*等。因此编写该TCP客户端类时,最好事先将需要使用的类所包含于的库文件引入所正在编写的java类文件的开头,当然也可以在事后添加。1.2.1 在TCP客户端的java源文件开头引用java库文件import .*;import java.io.*;这里介绍的一个最基本的TCP客户端程序中基本就只会使用上述java库文件中所包含的类了。大家可以根据编写的程序的需要,视情况引入更多的java库文件。1.2.2 与远程服务器端发起TCP连接请求TCP客户端要完成与远程服务器的TCP连接的工作,需要做以下几件事情:l 设定TCP服务器程序所运行的计算机网络接口地址(IP地址);l 设定TCP服务器程序所监听的网络端口号;l 向远程TCP服务器程序发起TCP连接请求;看似很多事情,其实在java中编程完成这些事情,相当简单。通常情况下,如果要连接某个远端服务器程序,那必然要知道该服务器程序所运行的主机IP地址或者该主机名。那么就可以通过运行该服务器程序的主机IP或主机名来在TCP客户端程序中构造一个InetAddress类对象实例。比如:主机IP = 23; 主机名 = whpucomputerInetAddress serverIP = InetAddress.getByName(“23”);或InetAddress serverIP = InetAddress.getByName(“whpucomputer”);光知道远程服务器程序所运行的主机地址还不够,TCP客户端程序还需要知道远程服务器程序所监听的端口号,通常在编程时端口号是一个整型数据。比如:该远程服务器程序所监听的端口号为:8888。知道了远程服务器程序所运行于的主机地址和其所监听的端口号后,就可以使用Socket类发起与远程服务器程序建立TCP连接的请求了,具体代码如下:Socket clientsock = new Socket(serverIP, 8888);上面代码复制符右端的Socket方法如果成功返回,那么就会返回一个Socket类对象的引用给Clientsock,在之后的程序中就可以使用这个Socket类对象引用来完成与远程服务器程序的通信工作了。不过,该段代码有个比较明显的问题:8888(端口号)被硬编码到代码中,这是一个不好的编程习惯。具体如何跟好的设置端口号,后面整体说明时进行解释。到此,TCP客户端编写发起向TCP服务器程序的TCP连接请求的代码就完成了,整体代码大致如下所示:InetAddress serverIP = InetAddress.getByName(“whpucomputer”);Socket clientsock = new Socket(serverIP, 8888);1.2.3 与远程TCP服务器程序进行通信基于java的TCP 套接字程序中,与远程网络程序进行通信主要使用的是Socket类中的两个类成员InputSteam和OutputStream这两个字节流对象。获取这两个Socket类的成员需要使用Socket类提供的两个方法:getInputStream和getOutputStream。在前面介绍的代码中,假设已经成功与远程服务器程序建立了一个TCP连接,并获取了一个Socket类对象的引用。那么获取InputStream和OutputStream的对象的代码如下:InputStream in = clientsock.getInputStream();OutputStream out = clientsock.getOutputStream();在java中使用文件流一般都不会直接使用InputStream和OutputStream类对象,一来直接使用字节访问数据比较麻烦,二来使用InputStream和OutputStream类对象会直接进行I/O操作,这样使用性能不高,特别是每次输入或输出的数据比较少的情况下,会反复进行I/O操作,由于每次I/O操作会耗费大量处理时间,因此势必带来运行效率不高的问题。 对InputStream的封装假如,我们想以字符的方式读取套接字的InputStream流对象中的字节数据,就可以对InputStream字节流对象进行封装,代码如下所示:InputStreamReader in = new InputStreamReader(clientsock.getInputStream();上面的代码只是将原来以字节访问方式的流转换为以字符方式访问的流,并没有改变I/O操作的方式,为了提高访问信息,我们需要为流提供缓冲区,以便不必每次操作流时都产生I/O操作。使用缓冲区时,有些问题必须注意。例如:对于输出流(OutputStream),只有在缓冲区已满或者显式的调用流的flush方法时,缓冲区中的数据才会真实的写入文件流,否则,不会执行将缓冲区数据写入输出流的操作;而对于输入流(InputStream),只要缓冲区未满,那么就可以接收外界向本地输入流传送来的数据,而在缓冲区已满时,表示外界向本地发送数据的速度快于本地处理输入流数据的速度,因此此时要拒绝再接收外界发送来的数据。为文件流提供缓冲功能的代码如下:BufferedReader in = new BufferedReader(new InputStreamReader(clientsock.getInputStream(); 对OutputStream的封装对于OutputStream文件字节流对象的封装基本和InputStream文件字节流对象封装的方式一致。具体代码如下:BufferedWriter out = new BufferedWriter(new InputStreamWriter(clientsock.getOutputStream();为了更容易的打印出缓冲区中的字符串,可以进一步对BufferedWriter对象进行封装,例如:PrintWriter out = new PrintWrite( new BufferedWriter(new InputStreamWriter(clientsock.getOutputStream();1.2.4 Client业务逻辑实现这里需要实现的Client功能如下描述:“循环10次,向Server端发送字符串”Hello Server” + i (i为整数,且0=i10),并接收Server的反馈信息,并将Server反馈信息打印到屏幕上。”在前面的代码基础上,我们已经有了一个与Server端的TCP连接的套接字对象:clientsock。并且也获得了该套接字对象的输入流和输出流,并进行功能需求的封装。根据上述Client功能描述,具体的代码实现如下:for(int i = 0; i 10; i +) out.println(hello Server + i); out.flush(); String str = in.readLine(); System.out.println(str); 以上代码中将循环执行10次的代码的工作内容如下:out是封装了套接字输出流的PrintWriter对象,调用PrintWriter对象的println方法,会将”Hello Server i”写入缓冲区中,然而,这并不意味着缓冲区的内容会写入到套接字的输出流对象中,只有调用out的flush方法后,缓冲区的数据才会发送到套接字的输出流对象,网路才有可能将数据发送出去。in.readLine()用来从本地套接字的输入流中读取Server端回馈的信息,如果,Server端没有回馈信息到来,那么该方法就会一直阻塞在哪里不会返回;而且就算Server端有数据返回,但是数据中没有/r/n,readLine方法同样不会返回,这就要求Server端回馈的数据最后一定要加上/r/n这两个字符,这可以手动添加到Server端连接套接字的输出流中,也可以直接使用PrintWriter对象的println方法,该方法会自动为字符串末尾添加/r/n。提示:在实际的网络应用程序中,避免使用Println和readLine方法,虽然这些方法在处理字符串方面非常简单好用,但是由于不同的操作系统的文本行结束符各不相同,这会导致跨平台的系统上运行包含了这些方法的网络程序时出现无法预料的问题,或者假死状态。1.2.5 TCP连接的关闭Client再不需要向Server端发送数据时,可以通过Socket类的close方法来关闭套接字,此时,如果系统套接字缓存中还有数据未发送,系统会尝试继续发送数据,TCP/IP协议栈也同时会向Server端发送一个FIN包,告知Server,客户端已经准备关闭套接字,如果Server端发挥ACK确认FIN包后,本次TCP连接进入半关闭状态。直到Server端的TCP/IP协议栈也发过来FIN包,并且Client端的TCP/IP协议栈发送对此次FIN包的ACK包后,整个TCP连接才完整关闭。当Clinet端调用了套接字的close方法后,如果Server端再次从连接套接字的输入流读取数据,会获得到达流末尾的提示,此时读取到的数据可能是-1或者null,通过这可以判断出TCP连接的远端程序已经关闭了套接字,本地也可以关闭TCP连接的套接字了。然而,这种靠底层TCP/IP协议机制来控制的套接字关闭的时机,不是特别理想。最好的方式是在Client和Server端之间协商一种应用层的连接结束的机制。例如:out.println(END); out.flush();在Client不想再保持连接时,就事先向Server端发送一个代表自己想断开TCP连接的意图。如上面代码所示,在Client发送完所有数据之后,向Server端发送一个字符串”END”。Server端在收到这个字符串后,就无需再为Client提供服务处理了,而关闭连接套接字。这种机制保证在Server端可以明确的知道Client的终断连接的意图。相比于通过TCP/IP发送的FIN包来判断Client已经断开的状态,这种方法肯定更好一些。在发送了”END”字符串后,Client就可以无需再去考虑Server端的情况,而直接调用套接字的close方法关闭套接字。clientsock.close();1.3 TCP Client 完整程序源码示例import java.io.*;import .*;public class Client public static void main(String args) throws IOException InetAddress addr = InetAddress.getByName(null); Socket socket = new Socket(addr, 8888); BufferedReader in = new BufferedReader( new InputStreamReader( socket.getInputStream(); PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter( socket.getOutputStream(); for(int i = 0; i data_size;c_recvbuff=c_sendbuff=s_recvbuff=s_sendbuffdata_size;实验要求:本次实验为验证性实验,主要目的是熟悉基于java的UDP套接字编写client/server模式网络应用程序的基本步骤和方法。实验后需按要求完成实验报告的撰写工作。实验报告内容格式应包含:1. 实验目的:2. 实验任务:3. 实验结果截图:4. 思考题回答:(如果有的话)5. 实验总结:实验3 基于多线程的TCP Echo 服务器实验目的:掌握java的多线程的编程方法;熟悉多线程的网络应用程序的编程方法;实验任务:在实验1的基础上,修改实验1中所编写的TCP Echo服务器程序,使之成为一个具有多线程工作能力的服务器程序。该服务器能够为每一个请求连接的客户端创建一个线程,为其提供通信服务。指导说明:1. Java线程的使用Java中使用线程的方法,主要是以下两步工作:1) 实现一个Runnable接口的类,该类主要负责指定子线程要做的工作;2) 在主线程中使用前面实现的Runnable接口类来创建一个Thread类实例,并启动该Thread类实例,使线程开始运行;2. 实现Runnable接口,完成与客户端的通信2.1 自定义实现一个Runnable接口类新建一个自定义接口类,框架如下:import java.io.*;import .*;public class EchoHandler implements Runnable /1.此处添加必要的类成员变量public EchoHandler()/2.这里是构造函数,主要用来在构造接口类实例时接受主线程传来的数据Overridepublic void run()/3.这里定义的代码,主要用来指明以此接口创建的线程的主要做什么?/1.private Socket connSocket; /用来接收主线程传入的参数private static final byte n /多次发送数据之间的分割符/2.public EchoHandler(Socket connSock)this.connSocket = connSock;/3Overridepublic void run()try byte msg = new byte1024; /接收数据本地缓冲 int recvByte; /保存每一次接收到的字节 int i = 0; /用于操作本地缓冲的index InputStream in = connectSock.getInputStream(); OutputStream out = connectSock.getOutputStream(); while(recvByte = in.read() != -1) /recvByte不等于-1 时循环 if (recvByte != DELIMITER) /recvByte不等于分隔符时,缓冲数据 msgi+ = (byte) recvByte; else /recvByte等于分隔符时,输出数据 System.out.println(Client send:+ new String(msg).trim(); i = 0; /重置缓冲index connectSock.close(); catch(IOException e) 1.1.2 在主线程中创建使用以上定义接口类的线程import java.io.*;import .*;public class MulitEchoServer public static void main(String args) /1.构造套接字地址 /2.构造未绑定地址的监听套接字(ServerSocket)类实例 /3.将监听套接字绑定到套接字地址 while(true)/4.监听套接字调用accept()方法,并接受返回的连接套接字(Socket)实例/5.以EchoHandler接口创建线程,并启动线程try /1. int PORT = 8888; SocketAddress serverAddr = new InetSocketAddress(PORT); /2. ServerSocket listener = new ServerSocket(); /3. listener.bind(serverAddr); while(true) /4. Socket connectSock = listener.accept(); /5. new Thread(new EchoHandler(connectSock).start(); catch(IOException e) 思考题:1、请查阅资料,从线程的状态、线程同步、资源互斥访问以及线程回收等方面,分析使用线程在解决问题时为什么在解决了性能问题的同时,带来了设计复杂度的急剧提升?2、尝试编写一个能够发起多线程连接的客户端,验证所设计服务器的服务性能。实验要求:本次实验为验证性实验,主要目的是熟悉基于java的多线程方式编写基于TCP 套接字的client/server模式网络应用程序的基本步骤和方法。实验后需按要求完成实验报告的撰写工作。实验报告内容格式应包含:1. 实验目的:2. 实验任务:3. 实验结果截图:4. 思考题回答:(如果有的话)5. 实验总结:实验4 基于NIO的TCP Echo客户端及服务器实验目的:掌握NIO的工作基本原理;熟悉NIO中用于网络的基本方法;熟悉Buffer类的基本操作方法;实验任务:编写基于非阻塞IO方式的Echo客户端和服务器程序。指导说明:1. NIO基本工作原理简述NIO的主要目的是以非阻塞的方式处理IO操作。基本思想是:所有的IO操作请求操作在应用层中都是立即返回的,而不会阻塞直到IO请求的操作完成后才返回。要做到这一点必须要有一个监控者,它监视着所有委托给它的IO对象所期待的操作事件是否完成,而当某个委托IO对象的操作完成时,就会通知对该IO对象的这个操作感兴趣的程序进行下一步操作。要理解NIO操作,就需要以分层的方式进行思考。比如:Java中基本IO操作都是面向于文件的,而文件最一般的理解就是它应该是磁盘存储的一个逻辑抽象。而对于文件的IO操作,不外乎最基本的读和写操作。假如:应用层要求对文件进行读的IO操作,该操作会调用系统层,系统层将应用层给出的要读数据的逻辑地址转换为数据实际存储于物理设备的物理地址,并调用磁盘硬件驱动程序,去操作真正的IO设备:磁盘。要读磁盘,至少要完成这么一些事情:根据系统发来的物理地址,进行寻道、寻扇区、读取数据到系统分配给磁盘的缓冲等。以上这些事情完成后,才表示应用层

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论