版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
在线教务辅导网:教材其余课件及动画素材请查阅在线教务辅导网QQ:349134187或者直接输入下面地址:1在线教务辅导网:http://www.shangfuwang11/17/20222作者:肖明学校:烟台大学计算机学院日期:2010年2月第四章
JAVA网路编程11/9/20222作者:肖明第四章
JAVA网路编程第四章JAVA网络编程4.1数据流4.2基于TCP协议的套接字通信4.1数据流4.4组播套接字4.5小结习题四3第四章JAVA网络编程4.1数据流3第四章JAVA网络编程Java的基于TCP/IP协议的客户端与服务器模式下的网络编程原理,涉及到的类主要有两个包:输入输出包:java.io网络包:。4第四章JAVA网络编程Java的基于TCP/IP协议的客户4.1数据流当前网络通信,都是由数据流(datastream)来处理的,因此,基于流通信(stream-basedcommunication)是Java网络编程的基础。数据流:是发送和接收信息的管道或通道,当数据通信管道建立起来,数据就可以从管道的一端传输到另一端。通信:是指在管道中流动的数据过程,这种数据流通信是以字节为基本数据单位,通过串行形式的数据序列顺序进行传输的过程。4.1.1数据流与网络技术的联系4.1.2流的工作方式4.1.3过滤器流、读取器和写入器4.1.4对象持久性和对象序列化54.1数据流当前网络通信,都是由数据流(datastre4.1.1数据流与网络技术的联系网络技术使得物理网络连通,在有效的协议控制下,实现信息传输,即套接字Socket的连接和通信。网络编程:是基于这种连通和相关协议控制下的套接字Socket实现网络的底层连接,再以流(stream)为类的操作,进行数据传输和流的关闭等。从另一个角度看,流为网络通信提供了统一的接口,使得网络通信更加规范和一致。64.1.1数据流与网络技术的联系网络技术使得物理网络连通4.1.1数据流与网络技术的联系在Java中,是以流(也就是类)来表示网络上的数据、文件或应用程序之间的通信。流划分为两种:输入流(inputstream):将数据从某个数据源发送到程序中;输出流(outputstream):将数据从程序中往外发送到某个目地端。输入、输出流的划分,极大地方便了编程。可以灵活地,分别独立地从输入流中读数据,接受数据,向输出流中写数据,发送数据,实现单向(one-way)或双向(two-way)通讯等。74.1.1数据流与网络技术的联系在Java中,是以流(也4.1.2流的工作方式在Java中,流是以字节级进行数据通信,为此分别提供了:字节输入流公用超类java.io.InputStream字节输出流公用超类java.io.OutputStream都是抽象类,也是基础性的底层字节输入输出类(流)。定义了公共的公有方法,通过两级子类继承,来实现这些方法和子类自己的方法。
84.1.2流的工作方式在Java中,流是以字节级进行数据两级子类继承字节输入、输出流公用超类继承关系一级子类FilterInputStreamInputStreamFilterOutputStreamOutputStreamDataInputStreamDataOutputStreamBufferedInputStreamBufferedOutputStreamDataInputDataOutputObject字节输出流接口ObjectInputStream……图4.1字节输入、输出流公用超类继承关系…………字节输入流过滤输入流过滤输出流公用超类二级子类数据输入流数据输出流缓冲输入流缓冲输出流ObjectOutputStream……9两级子类继承字节输入、输出流公用超类继承关系一级子类Fil第一级继承有4或6个子类不等,其中数据源包括:字节数组(ByteArray)字符串(String)文件(File)管道(Pipe)过滤器(Filter)其他等数据源与网络通信有关的InputStream和OutputStream的子类是:过滤器输入流FilterInputStream过滤器输出流FilterOutputStream这两个类也是抽象类10第一级继承有4或6个子类不等,其中数据源包括:与网络通信有关第二级继承在过滤器流的基础上继承,有10或8个子类,基本上都与网络通信有关,其中常用的是:过滤器输入流FilterInputStream的子类:数据输入流DataInputStream缓冲输入流BufferedInputStream数据输入流接口DataInput;过滤器输出流FilterOutputStream的子类:数据输出流DataOutputStream缓冲输出流BufferedOutputStream数据输出流接口DataOutput;11第二级继承在过滤器流的基础上继承,有10或8个子类,基本上都与网络通信有关的流工作方式指创建过滤器输入流子类或过滤器输出流子类与套接字通信绑定的对象方式。有了这些流对象就可以调用其方法完成底层字节流的套接字网络数据通信。在具体设计上是两个程序,分别装在网络上的两台计算机上。在互联网上,有三种模式:点对点的P2P(peer-to-peer)模式,又称对等互联网络技术,客户端和服务器(C/S)体系结构浏览器和服务器(B/S)体系结构12与网络通信有关的流工作方式指创建过滤器输入流子类或过滤器输出4.1.3过滤器流、读取器和写入器过滤器流具有缓冲区的过滤器流BufferedInputStream和BufferedOutputStream流对数据访问时可提高效率。访问不同数据类型的过滤器流DataInputStream和DataOutputStream流提供了访问各种不同数据类型的方法过滤器流的特点在进行读写数据的同时,还可进行数据处理,方便了网络编程。134.1.3过滤器流、读取器和写入器过滤器流13读取器Reader和写入器Writer它们均为IO包中的类,都是抽象的公用超类。它们也是通过其子类继承实现读入和写出。不同点是读写器以字符流操作应用程序以字符形式输入和输出速度更快、功能更强,但需要将字符转换成字节来实现网络通信。14读取器Reader和写入器Writer它们均为IO包中的类,1.过滤器流指过滤器输入流FilterInputStream和过滤器输出流FilterOutputStream,这两个抽象类,以及所对应的子类。过滤器输入流FilterInputStream,通过其子类继承实现输入流操作,共有10个子类:151.过滤器流指过滤器输入流FilterInputStream过滤器输入流FilterInputStream的子类⑴数据输入流DataInputStream定义:publicclassDataInputStreamextendsFilterInputStreamimplementsDataInput构造函数:DataInputStream(InputStreamin)方法如下:intread(byte[]b)booleanreadBoolean()doublereadDouble()floatreadFloat()bytereadByte()shortreadShort()intreadInt()longreadLong()StringreadUTF()16过滤器输入流FilterInputStream的子类⑴数据过滤器输入流FilterInputStream的子类⑵数据输出流DataOutputStream定义:publicclassDataOutputStreamextendsFilterOutputStreamimplementsDataOutput构造函数:publicDataOutputStream(OutputStreamout)方法如下:publicfinalintsize()以下方法修饰为public,返回值为void:flush(),清空此数据输出流。write(intb)write(byte[]b,intoff,intlen)writeBoolean(Booleanv)writeByte(intv)writeBytes(Strings)writeChar(intv)publicfinalvoidwriteUTF(Stringstr)writeDouble(doublev)writeFloat(floatv)writeInt(intv)writeLong(longv)writeShort(intv)17过滤器输入流FilterInputStream的子类⑵数据⑶缓冲输入流BufferedInputStream定义:publicclassBufferedInputStreamextendsFilterInputStream构造函数:publicBufferedInputStream(InputStreamin)publicBufferedInputStream(InputStreamin,intsize)创建一个带有基本输入流in为参数的缓冲输入流。此缓冲区是内部缓冲区数组buf。size为设定的缓冲区大小。方法如下:read(),从输入流中读取一个数据字节。返回一个0到255范围内的int字节值。read(byte[]b,intoff,intlen),从此字节输入流中给定起始位置off,开始读取长度len个字节数到指定的byte数组中。b为目标缓冲区。off为开始存储字节处的偏移量。len要读取的最大字节数。18⑶缓冲输入流BufferedInputStream定义:1⑷缓冲输出流BufferedOutputStream定义:publicclassBufferedOutputStreamextendsFilterOutputStream构造函数:publicBufferedOutputStream(OutputStreamout)publicBufferedOutputStream(OutputStreamout,intsize)创建一个缓冲输出流,以将数据写入指定的底层输出流。Out为底层输出流;size为设定的缓冲区大小。方法如下:write(intb),将指定的字节写入此缓冲的输出流。write(byte[]b,intoff,intlen),将指定byte数组中从位置off开始的长度len个字节写入此缓冲的输出流。b为数据;off为数据的起始偏移量;len为要写入的字节数。flush(),刷新此缓冲的输出流。这迫使所有缓冲的输出字节被写出到底层输出流中。19⑷缓冲输出流BufferedOutputStream定义:2.读取器和写入器在网络通信中,是以字节为单位,就必须将字符流转换成字节流,才能实现读取器和写入器的网络通信。重点讨论与实现网络编程有关的读写器子类和转换器。读取器Reader的子类(流),BufferedReader和InputStreamReader,写入器Writer的子类BufferedWriter、OutputStreamWriter和PrintWriter都与网络编程有关。202.读取器和写入器在网络通信中,是以字节为单位,就必须将字符2.读取器和写入器⑴缓冲字符读取器BufferedReader定义:publicclassBufferedReaderextendsReader构造函数:publicBufferedReader(Readerin)publicBufferedReader(Readerin,intsz)方法如下:readLine(),读取一个文本行;read(),读取单个字符。⑵字节流与字符流输入转换器InputStreamReader定义:publicclassInputStreamReaderextendsReader构造函数:publicInputStreamReader(InputStreamin)publicInputStreamReader(InputStreamin,Charsetcs)publicInputStreamReader(InputStreamin,CharsetDecoderdec)publicInputStreamReader(InputStreamin,StringcharsetName)对应的方法在此不讨论,可参考相关资料。212.读取器和写入器⑴缓冲字符读取器BufferedRead2.读取器和写入器⑶缓冲字符写入器BufferedWriter定义:publicclassBufferedWriterextendsWriter构造函数:publicBufferedWriter(Writerout)publicBufferedWriter(Writerout,intsz)方法如下:flush();write(char[]cbuf,intff,intlen);write(intc);write(Strings,intoff,intlen)⑷字符流与字节流输出转换器OutputStreamWriter定义:publicclassOutputStreamWriterextendsWriter构造函数:publicOutputStreamWriter(OutputStreamout)对应的方法在此不讨论,可参考相关资料。222.读取器和写入器⑶缓冲字符写入器BufferedWrit2.读取器和写入器⑸字符格式化文本输出流PrintWriter字符格式化文本输出流,它不包含用于写入原始字节的方法,对于这些字节,程序应该使用未编码的字节流进行写入。定义:publicclassPrintWriterextendsWriter构造函数:publicPrintWriter(Writerout,booleanautoFlush),参数:out为字符输出流。autoFlush为boolean变量,如果为true,则println、printf或format方法将刷新输出缓冲区。方法如下:print(Strings),输出字符串s。按照默认字符编码转换为字节,以write(int)方法写入这些字节。println(Stringx),输出字符串x,然后终止该行。format(Stringformat,Object...args),使用指定格式字符串和参数将一个格式化字符串写入此writer中。返回PrintWriter对象。如果启用自动刷新,则调用此方法将刷新输出缓冲区。232.读取器和写入器⑸字符格式化文本输出流PrintWrit3.网络通信中
基于套接字输入流和输出流的创建要实现套接字的网络通信,需要分四个步骤来完成:①创建套接字socket(Socket),连接成功后形成网络连接通道;②完成绑定套接字通信的输入流和输出流对象的创建;③用输入和输出流对象调用其对应方法的操作方式实现网络通信;④网络通信结束,需要关闭输入流和输出流对象,尤其要关闭套接字对象。243.网络通信中
基于套接字输入流和输出流的创建要实现套接字的⑴基于套接字的字节输入流dis和输出流dos的创建,以及网络编程实例importjava.io.*;import.*;publicclassDS_Client4_1{ publicstaticvoidmain(String[]args)throwsIOException{
//①建立Socket,服务器在本机的8888端口处进行“侦听” Socketsocket=newSocket("",8888);//建立套接字 System.out.println("客户端套接字信息:"+socket); try{//②套接字建立成功后,建立字节输入流dis和输出流dos对象 DataInputStreamdis=newDataInputStream(socket.getInputStream()); DataOutputStreamdos=newDataOutputStream(socket.getOutputStream());
//③调用其对应方法进行网络通信 for(inti=0;i<6;i++){ dos.writeUTF("客户端测试:"+i); //向服务器发数据 dos.flush(); //刷新输出缓冲区,以便立即发送 System.out.println(dis.readUTF()); //将从服务器接收的数据输出 } dos.writeUTF("end"); //向服务器发送终止标志 dos.flush(); //刷新输出缓冲区,以便立即发送
//④关闭对象 dos.close();//关闭输出流对象dos dis.close();//关闭输入流对象dis }finally{ System.out.println("客户端结束……"); socket.close();//关闭套接字对象socket } }}25⑴基于套接字的字节输入流dis和输出流dos的创建,以及网⑵基于套接字的具有缓冲的字节输入流dinB和输出流dosB的创建importjava.io.*;import.*;publicclassBP_Client4_2{publicstaticvoidmain(String[]args)throwsIOException{ //①建立Socket,服务器在本机的8888端口处进行“侦听” Socketsocket=newSocket("",8888);//建立套接字 try{
//②套接字建立成功后,通过转换器建立字符输入流br和自动刷新输出流pw BufferedReaderbr=newBufferedReader( newInputStreamReader( socket.getInputStream())); PrintWriterpw=newPrintWriter( newBufferedWriter(newOutputStreamWriter( socket.getOutputStream())),true);转换器转换器26⑵基于套接字的具有缓冲的字节输入流dinB和输出流dosB
//③调用其对应方法进行网络通信 for(inti=0;i<10;i++){ //向服务器发数据,并自动刷新输出缓冲区pw.println("测试:"+i); Stringstr=br.readLine();//从服务器接收数据 System.out.println(str);//将从服务器接收的数据输出 } //向服务器发送终止标志,并自动刷新输出缓冲区pw.println("end");
//④关闭对象 pw.close();//关闭输出流对象pw br.close();//关闭输入流对象br }finally{ System.out.println("结束……"); socket.close();//关闭套接字对象socket }}}27 //③调用其对应方法进行网络通信274.1.4对象持久性和对象序列化对象序列化:将对象转换为可保持或传输的格式的过程。就是将整个对象写入字节流中,这样形成字节流序列才能在网络上传输,也可以将对象保存在文件中。反序列化:它将流转换为对象。对象的反序列化,把接收到的字节流序列或文件完全恢复成原来的对象。对象持久性:指保持对象,甚至在多次执行同一程序之间也能保持对象。对象的网络传输或保存到文件中就是对象持久化,它不随本地主机的程序终止而消失或被破坏。对象持久性和序列化可以实现分布式对象。在Java中,java.io包中的ObjectInputStream类和ObjectOutputStream类,分别为对象输入流和对象输出流,以及Serializable接口构成实现对象序列化基本类和接口。
284.1.4对象持久性和对象序列化对象序列化:28ObjectInputStream和ObjectOutputStrea类定义:publicclassObjectInputStreamextendsInputStreamimplementsObjectInput,ObjectStreamConstantspublicclassObjectOutputStreamextendsOutputStreamimplementsObjectOutput,ObjectStreamConstants构造函数:publicObjectInputStream(InputStreamin)throwsIOException,创建从指定in读取对象流。publicObjectOutputStream(OutputStreamout)throwsIOException,创建指定out的写入对象流。常用方法publicfinalObjectreadObject()throwsIOException,ClassNotFoundException,从对象输入流读取对象。publicfinalvoidwriteObject(Objectobj)throwsIOException,将指定的对象写入对象输出流。异常:ClassNotFoundException找不到序列化对象的类。IOException任何常规的输入/输出相关的异常。29ObjectInputStream和ObjectOutput对象持久性和对象序列化的网络编程实例通过服务器(例程4-3)对象序列化在网络上传输,发送至客户端;客户端(例程4-4)接收后反序列化恢复为原多行文本框控件,并显示。先运行服务器程序,即例程4-3,再运行客户端程序,即例程4-4例程4-3对象序列化服务器程序,OS_Server4_3.java例程4-4对象反序列化客户端程序,OS_Client4_4.java程序对象序列化和反序列化是一个封装多行文本框控件的类boy。30对象持久性和对象序列化的网络编程实例通过服务器(例程4-34.2基于TCP协议的套接字通信在Internet上使用得最普遍的通信方式是基于TCP协议的套接字(Socket)的通信,它把用户代码与TCP/IP协议的底层实现隔离开了。用户可快速地开发出自定制的客户端和服务器应用程序。4.2.1TCP套接字4.2.2Socket类4.2.3ServerSocket类4.2.4异常处理4.2.5TCP网络通信实例314.2基于TCP协议的套接字通信在Internet上使用得4.2.1TCP套接字一个套接字Socket就是在网络上运行的两个程序间的双向通信通道的一个端点,两个程序通过各自的套接字实现程序间的与网络拓扑结构无关的通信。客户端程序和服务器必须使用同样的通信协议,这就是TCP协议,即它们在传送的信息所使用的语言上达成一致。在Java的包中提供了两个套接字类,如客户端程序的套接字Socket和服务器端的套接字SererSocket,它们很好地支持了TCP套接字。另外包还提供了表示互联网IP地址的InetAddress类,用来设置或获取IP地址和主机域名(DNS)。见例程4-5InetAddress类的使用程序InetAddressTest4_5.java套接字通信是利用IP地址和端口Port进行的,是一种基础性的底层连接。一般步骤是:首先,服务器“侦听”其端口进入的连接。其次,客户端套接字cS与服务器的端口连接建立套接字sS级别的连接通道。再次,客户端与服务器分别通过绑定sS和cS套接字连接通道的输入输出流操作,实现网络通信与服务。324.2.1TCP套接字一个套接字Socket就是在网络上4.2.2Socket类Socket类为客户端的通信套接字。以下三个功能:由构造函数,定义指定远端IP地址、端口进行连接通信的通信套接字socket。将此socket以字节输入流和输出流的形式返回,当与数据输入流和输出流绑定,便可实现客户端的网络通信。也可通过方法获得已连接的socket的远端IP地址、端口。1.Socket定义和构造函数2.返回输入流和输出流的方法3.获取Socket信息方法334.2.2Socket类Socket类为客户端的通信套接1.Socket定义和构造函数Socket构造函数均为public修饰类型,如果创建socket时发生I/O错误,均抛出IOException异常。定义和常用的构造函数如下:定义:publicclassSocketextendsObject构造函数:Socket(InetAddressaddress,intport)创建一个socket并与指定的IP地址的指定的端口相连接。address为指定的IP地址。port为指定的端口。Socket(Stringhost,intport)创建一个socket并与指定的主机的指定的端口相连接。host为指定的主机的字符串名。port为指定的端口。如果无法确定主机的IP地址还抛出UnknownHostException异常。341.Socket定义和构造函数Socket构造函数均为pub2.返回输入流和输出流的方法publicInputStreamgetInputStream()throwsIOException返回此套接字的输入流。publicOutputStreamgetOutputStream()throwsIOException返回此套接字的输出流。套接字建立成功后,建立字节输入流dis和输出流dos对象:DataInputStreamdis=newDataInputStream(socket.getInputStream());DataOutputStreamdos=newDataOutputStream(socket.getOutputStream());352.返回输入流和输出流的方法publicInputStre3.获取Socket信息方法此类方法可获取socket所连接的远端IP地址、端口号,及所绑定的本地IP地址、端口号。另外,socket用完需要用方法关闭。方法如下:publicInetAddressgetInetAddress()获取socket所连接的远端IP地址。publicInetAddressgetLocalAddress()获取socket所绑定的本地IP地址。publicintgetPort()获取socket所连接的远端端口号。publicintgetLocalPort()获取socket所绑定到的本地端口号。publicvoidclose()throwsIOException关闭socket。StringtoString()将此socket转换为String。363.获取Socket信息方法此类方法可获取socket所连接4.2.3ServerSocket类ServerSocket类为服务器的通信套接字。用来侦听客户端请求的连接,并为每个新连接创建一个socket对象,由此创建绑定此socket的输入流和输出流,与客户端实现网络通信。1.定义与构造函数2.常用成员方法374.2.3ServerSocket类ServerSock1.定义与构造函数定义:publicclassServerSocketextendsObject构造函数:ServerSocket(intport)在所给定的用来侦听的端口上建立一个服务器套接字。如果端口号为零,则在任意的空闲的端口上创建一个服务器套接字。外来连接请求的数量默认最大为50。port参数为在服务器上所指定的用来侦听的端口。ServerSocket(intport,intbacklog)在所给定的用来侦听的端口上建立一个服务器套接字。如果端口号为零,则在任意的空闲的端口上创建一个服务器套接字。外来连接请求的最大连接数量由backlog指定。381.定义与构造函数定义:382.常用成员方法此类方法关键是侦听连接端口,建立与客户端的套接字连接。服务器套接字用完需要用方法关闭。方法如下:publicSocketaccept()throwsIOException侦听并接收指向本套接字的连接,返回客户端连接套接字。本方法将造成阻塞直到连接成功。如果在等待连接时套接字发生I/O错误,则抛出异常IOException。publicvoidclose()throwsIOException关闭本ServerSocket。如果在关闭本ServerSocket时发生I/O错误,则抛出异常IOException。publicInetAddressgetInetAddress()获取此服务器端套接字的本地IP地址。publicintgetLocalPort()获取此套接字侦听的端口。StringtoString()作为String返回此套接字的实现IP地址和实现端口。392.常用成员方法此类方法关键是侦听连接端口,建立与客户端的套建立数据输入流dis过程服务器端程序。建立数据输入流dis和输出流过程类似。以创建和使用输入流dis为例。ServerSockets=newServerSocket(PORT);DataInputStreamdis=:侦听PORT端口,获得客户端套接字Socketss=s.accept();newDataInputStream(ss.getInputStream());while(true){//从客户端中读数据Stringstr=dis.readUTF();}创建捆绑客户端套接字的数据输入流建立服务器ServerSocket套接字通过数据输入流操作读取数据40建立数据输入流dis过程服务器端程序。建立数据输入流dis和例程4-6服务器端程序DS_Server4_6.javaimportjava.io.*;import.*;publicclassDS_Server4_6{ publicstaticfinalintPORT=8888; publicstaticvoidmain(String[]args)throwsIOException{ ServerSockets=newServerSocket(PORT);//建立服务器ServerSocket套接字 System.out.println("服务器套接字信息:"+s); try{//程序阻塞,等待连接。即直到有一个客户请求到达,程序方能继续执行 Socketss=s.accept();//侦听PORT端口,获得客户端套接字 System.out.println("套接字接收到的信息:"+ss); try{//连接成功,建立相应的数据输入输出流 DataInputStreamdis=newDataInputStream(ss.getInputStream()); DataOutputStreamdos=newDataOutputStream(ss.getOutputStream()); //在死循环中,来与客户端通信 while(true){// Stringstr=dis.readUTF(); //从客户端中读数据 if(str.equals("end"))break;//当读到end时,程序终止 System.out.println(str); dos.writeUTF("服务器应答:"+str);//向客户端中写数据 } dos.close();//关闭输出流对象dos dis.close();//关闭输入流对象dis }finally{ ss.close();//关闭套接字 } }finally{ System.out.println("服务器结束……"); s.close();//关闭服务器套接字 } }}41例程4-6服务器端程序DS_Server4_6.javaim4.2.4异常处理IOException异常Socket类发生I/O错误,出现异常,是在创建套接字时、在连接期间发生错误时、关闭套接字时、绑定操作失败或者已经绑定了套接字时、在创建输入流时或没有关闭套接字或没有连接套接字或关闭了套接字输入、创建输出流时或者没有连接套接字时,系统均会抛出IOException异常。ServerSocket类也发生I/O错误,出现异常,是在打开套接字时、关闭套接字时、绑定操作失败或者已经绑定了套接字、等待连接时,系统则会抛出IOException异常。这类通用的异常,采用try/catch/finally结构来抛出、捕捉和处理就可以了。424.2.4异常处理IOException异常424.2.5TCP网络通信实例在上例(例程4-1和例程4-6)中,为单线程通信。用多线程机制实现服务器能同时处理多个客户端的请求与聊天。常用的方法是在服务器程序中,accept()返回一个socket后,就用它新建一个线程,令一个线程只为它特定的客户服务。然后再调用accept(),等待下一次新的连接请求,同时产生下一个新的客户线程。例程4-7和例程4-8是一个多线程服务器和客户端网络程序,可服务多个客户的。可以看到它与上例很相似,只是将为一个特定的客户提供服务的所有操作都已移入一个独立的线程类中。434.2.5TCP网络通信实例在上例(例程4-1和例程4-例程4-7:多线程服务器端程序MBP_Server4_7.javaimport.*;importjava.io.*;publicclassMBP_Server4_7{publicstaticfinalintPORT=8888;publicstaticvoidmain(String[]args)throwsIOException{ServerSocketss=newServerSocket(PORT);//创建服务器套接字System.out.println("服务器开启!");try{while(true){Sockets=ss.accept();//侦听服务器定端口PORT,接收客户端套接字try{newServerOne(s);//启动一个新的线程,并把accept()得到的socket传入新线程中}catch(IOExceptione){s.close();//关闭套接字}}}finally{ss.close();//关闭服务器套接字}}}//用于为特定用户服务的线程类classServerOneextendsThread{privateSockets;privateBufferedReaderin;privatePrintWriterout;publicServerOne(Sockets)throwsIOException{this.s=s;//创建缓冲字符读入器in和字符文本输出流outin=newBufferedReader(newInputStreamReader(s.getInputStream()));out=newPrintWriter(newBufferedWriter(newOutputStreamWriter(s.getOutputStream())),true);start(); //启动}publicvoidrun(){ //线程自动运行try{while(true){Stringstr=in.readLine();//接收客户端信息if(str.equals("end"))break;System.out.println("服务器:接收客户端信息:"+str);out.println("Echo:"+str);//向客户端发送信息}System.out.println("closing…");}catch(IOExceptione){}finally{try{s.close();//关闭套接字}catch(IOExceptione){}}}}44例程4-7:多线程服务器端程序MBP_Server4_7.j例程4-8:多线程客户端程序MBP_Client4_8.javaimport.*;importjava.io.*;publicclassMBP_Client4_8extendsThread{//允许创建的线程的最大数staticfinalintMAX_THREADS=25;privatestaticintid=0;//每一个线程的id都不同privatestaticintthreadCount=0;//当前活动的线程数privateSockets;privateBufferedReaderin;privatePrintWriterout;publicstaticintgetThreadCount(){returnthreadCount;}publicMBP_Client4_8(InetAddressia){threadCount++;id++;System.out.println("Makingclient:"+id);try{s=newSocket(ia,MBP_Server4_7.PORT);//创建套接字}catch(IOExceptione){}try{//创建缓冲字符读入器in和字符文本输出流outin=newBufferedReader(newInputStreamReader(s.getInputStream()));out=newPrintWriter(newBufferedWriter(newOutputStreamWriter(s.getOutputStream())),true);start(); //启动}catch(IOExceptione1){try{s.close();//关闭套接字}catch(IOExceptione2){}}}publicvoidrun(){//线程自动运行try{Stringstr;for(inti=0;i<5;i++){out.println("Client#"+id+":"+i);//发送信息str=in.readLine();//接收服务器信息System.out.println("客户端:发送信息#"+id+":"+i+",服务器应答信息:"+str); }out.println("end");//告知服务器本线程结束}catch(IOExceptione){}finally{try{s.close();}catch(IOExceptione){}}}publicstaticvoidmain(String[]args)throwsIOException,InterruptedException{InetAddressia=InetAddress.getByName(null); //参数null代表本地主机while(true){if(getThreadCount()<MAX_THREADS)newMBP_Client4_8(ia);//新建客户端线程elsebreak;//当前线程数大于MAX_THREADS,退出结束
//当前运行的线程休眠(暂停执行)10msThread.currentThread().sleep(10);}}}45例程4-8:多线程客户端程序MBP_Client4_8.ja4.3基于UDP协议的
数据报和套接字用户数据报协议UDP与TCP协议相反,它并不刻意追求数据报会完全发送出去,也不能担保它们抵达的顺序与它们发出时是一样的,是一种不可靠数据传输协议。比TCP协议具有开销少、传输速度快。
4.3.1UDP概述4.3.2DatagramPacket类4.3.3DatagramSocket类4.3.4构建UDP客户端/服务器4.3.5UDP网络应用实例464.3基于UDP协议的
数据报和套接字用户数据报协议UDP4.3.1UDP概述Java中实现UDP协议的两个类DatagramPacket数据包类:将数据打成UDP数据包,也可将接收的UDP数据包解包成数据;DatagramSocket数据报套接字类:用于发送和接收UDP数据报。不分客户端和服务器套接字。用户接收数据时,从DatagramSocket接收DatagramPacket对象,并读取数据包的内容。474.3.1UDP概述Java中实现UDP协议的两个类474.3.2DatagramPacket类数据包DatagramPacket类所定义的对象表示为一个数据包,依据设定可确定数据包的大小。每个数据包中应该包含:源和目标地址、源和目标端口这些信息。才能在网络上通过路由器选定的路径传输,从始发源主机传送到目的主机。484.3.2DatagramPacket类数据包Datag1.DatagramPacket的定义和构造函数定义:publicfinalclassDatagramPacketextendsObject构造函数:publicDatagramPacket(byte[]buf,intlength):buf表示接收数据的缓冲区;length表示接收数据的最大长度,它必须小于等于buf.length,通常为buf的长度。publicDatagramPacket(byte[]buf,intoffset,intlength):offset为在缓冲区中指定了偏移量。publicDatagramPacket(byte[]buf,intlength,InetAddressaddress,intport):创建数据报包。buf中存放发送的数据;length表示发送数据的长度;address表示目的地址;port表示目的端口号。DatagramPacket(byte[]buf,intoffset,intlength,InetAddressaddress,intport):offset为在缓冲区中指定了偏移量。491.DatagramPacket的定义和构造函数定义:pub2.常用方法publicInetAddressgetAddress():发送数据包时,返回接收数据包的主机的IP地址;接收数据包时,返回发出数据包的主机IP地址。publicintgetPort():发送数据包时,返回接收数据包的主机端口号;接收数据包时,返回发出数据包的主机端口号。publicintgetLength():返回被接收或发送的数据的长度。publicbyte[]getData():返回被接收或发送的缓冲区数据。publicintgetOffset():返回被接收或发送的数据的偏移量。publicvoidsetAddress(InetAddressiaddr):发送数据包时,设置返回接收数据包的主机IP地址;接收数据包时,设置返回发出数据包的主机IP地址。publicvoidsetPort(intiport):远程主机上的端口号。publicvoidsetLength(intlength):为此包设置长度。publicvoidsetData(byte[]buf):数据缓冲区。502.常用方法publicInetAddressgetAd4.3.3DatagramSocket类在客户端和服务器都需要建立一个DatagramSocket对象,然后通过receive()方法接收数据包,通过send()方法发送数据包。无须像TCP协议套接字一样,还要建立会话流来传送数据。1.DatagramSocket的定义和构造函数2.常用方法514.3.3DatagramSocket类在客户端和服务器1.DatagramSocket的定义和构造函数定义:publicclassDatagramSocketextendsObject构造函数:publicDatagramSocket()throwsSocketException:创建数据报套接字,系统自动将它与本地主机上的某个可使用的端口绑定在一起。publicDatagramSocket(intport)throwsSocketException:创建数据报套接字,并将它与本地主机的一个指定的端口(port)绑定在一起。publicDatagramSocket(intport,InetAddressladdr)throwsSocketException:创建数据报套接字,将其绑定到指定的本地laddr地址和端口port。抛出异常SocketException:如果数据报套接字不能被创建或不能与本地端口联系起来,就抛出异常。521.DatagramSocket的定义和构造函数定义:pub2.常用方法publicvoidreceive(DatagramPacketp)throwsIOException:从数据报套接字接收一个数据包。本方法返回时,数据包p中存放被接收的数据,且数据包中也含有发送地的IP地址和端口号。如果发生IO错误,就抛出异常IOException。publicvoidsend(DatagramPacketp)throwsIOException:发送数据包DatagramPacket将包括数据内容、数据长度、目的IP地址和端口的信息。抛出异常IOException。publicvoidclose():关闭套接字。publicInetAddressgetLocalAddress():获取套接字绑定的本地地址。publicintgetLocalPort():获取此套接字绑定的本地主机上的端口号532.常用方法publicvoidreceive(Data4.3.4构建UDP客户端/服务器服务器:建立数据包DatagramPacket的对象,未知客户端的IP和Port,但需要设置数据缓冲区的大小。建立数据报套接字DatagramSocket的对象时,需要确定和绑定服务器端口Port,以便由此端口接收客户端数据包。服务器先接收客户端发来的数据包,然后发送数据包。客户端:建立数据包DatagramPacket的对象时,必须已知目的(服务器)InetAddress地址和端口Port,并设置,以便数据包发送至目的地,确定数据包缓冲区大小。建立数据报套接字DatagramSocket的对象时,可不设定端口,系统自动获取客户端端口Port。客户端先发送数据包,后接收数据包。544.3.4构建UDP客户端/服务器服务器:54例程4-9:UDP协议服务器程序UDPServer4_9.javaimport.*;publicclassUDPServer4_9extendsObject{publicstaticfinalintPORT=8765; //服务器端口publicstaticvoidmain(Stringargs[]){try{);//建立指定端口Port的数据报套接字对象DatagramSocketdgs=newDatagramSocket(PORTbyte[]buf=newbyte[1024];//建立数据包对象,未知客户端的IP和Port,自动带自己(服务器端)的IP和PortDatagramPacketp=newDatagramPacket(buf,buf.length);System.out.println("服务器启动!");for(inti=0;i<3;i++){dgs.receive(p); //服务器收到数据包,带有客户端的IP和PortSystem.out.println("服务器收到数据报:#"+i+";"+newString(p.getData(),0,p.getLength()));dgs.send(p); //向客户端发送带有客户端的IP和Port的数据包p}}catch(Exceptione){e.printStackTrace();}}}55例程4-9:UDP协议服务器程序UDPServer4_9.j例程4-10:UDP协议客户端程序UDPClient4_10.javaimport.*;publicclassUDPClient4_10extendsObject{publicstaticInetAddressia;publicstaticfinalintPORT=8765; //服务器端口publicstaticStringstr="你好!"; //发送内容publicstaticvoidmain(Stringargs[]){try{//服务器主机IP地址ia=InetAddress.getLocalHost(); DatagramSocketdgs=newDatagramSocket();//数据报套接字对象,自动分配端口号byte[]buf=newbyte[1024];buf=str.trim().getBytes(); //发送内容//建立数据包对象(设置有服务器的IP和Port,自动加载自己(客户端)的IP和Port)DatagramPacketp=newDatagramPacket(buf,buf.length,ia,PORT);for(inti=0;i<3;i++){dgs.send(p);//客户端向服务器发送带有服务器端的IP和Port的数据包pSystem.out.println("客户端发送完毕数据报!");dgs.receive(p); //客户端接收数据包System.out.println("客户端接收到返回的数据报:#"+i+";"+newString(p.getData(),0,p.getLength()));Thread.sleep(900);}}catch(Exceptione){e.printStackTrace();}}}56例程4-10:UDP协议客户端程序UDPClient4_104.3.5UDP网络应用实例例程4-11是一个多线程点对点的UDP协议网络应用实例。该程序由三部分组成:登录设置对话框(setDialog)、数据发送与接收窗口(DSR_Frame)和客户线程(LoginClient)。本程序主要实现如下功能:①设置用户名、用户主机端口和对话客户的IP地址和端口。②每个用户可同时发送和接收信息。③两个用户间对话和通过改变IP地址和端口设置与其他用户对话。程序启动后,打开“登录设置”对话框,先设置用户名、对方主机名IP、对方端口和自己接收端口,单击“确定”按钮,进入“数据发送与接收”窗口。对方主机名IP和发送对方端口必须事先知道,并正确设置,双方才能正常发送和接收数据。例如,用户名:“北京”,对方主机名IP:“”,发送对方端口:“777”,自己接收端口:“666”;另一用户名:“上海”,则发送对方端口只能是“666”,自己接收端口也只能是“777”。先启动程序按用户名“北京”设置,再启动程序按用户名“上海”设置,这样两人就可以相互发送与接收数据。也可以打开第三个用户,第三个用户能和谁进行数据发送和接收,取决于发送对方的端口设置。574.3.5UDP网络应用实例例程4-11是一个多线程点对4.4组播套接字组播传递(MulticastDelivery)技术越来越多地应用于网络数据传输,它更适合于网络多媒体业务。在Java中,为实现IP组播(1P多点传送)包中提供了MulticastSocket类称组播套接字和在组内发送和接收DatagramPacket数据包。4.4.1组播传播方式4.4.2组播Socket类4.4.3组播Socket的实例584.4组播套接字组播传递(MulticastDelive4.4.1组播传播方式网络数据传输按照接收者的数量,可分为三种方式:单播(Unicast)传输:在发送者和每一个接收者之间实现点到点网络连接。广播(Broadcast)传输:指在IP子网内广播数据包,所有在子网内部的主机都将收到这些数据包中。电视台就是采用广播方式。组播(Multicast)传输:发送者每次发送的数据可以被组内的所有接收者收到。在组内的发送者和每一个接收者之间实现点到多点网络传输,也称多点传送。组播是介于单播传输和广播传输之间的一种中间技术。它可大大提高数据传送效率,减少了骨干网络出现拥塞的可能性。比前两种方式的效率都很高。594.4.1组播传播方式网络数据传输按照接收者的数量,可分图4-2组播与非组播数据包传输和复制过程组播传输,仅在通过的路由器2和路由器4上的数据被复制传输,在其余结点上无须复制数据。在主机1通过路由器1到路由器2的传输路径上,数据只需传送一次。而非组播传输,路由器1发送4个独立的相同数据流到路由器2,再到每台主机上。60图4-2组播与非组播数据包传输和复制过程组播传输,仅在组播地址组播组内的所有主机共享同一个地址。组播地址使用的是D类IP地址,它的最高二进制四位为“1110”,十进制范围为~55。永久组播地址:大多数以224.0、224.1、224.2或239开头的地址。临时组的组播地址:可以在创建新的组播时由用户选取,~55。本地管理组播地址:~55。组播组是开放的,主机可以在任何时候进入或离开组。61组播地址组播组内的所有主机共享同一个地址。61数据包的生存期TTL(TimeToLive)组播分组在网络上的转发是由支持组播的路由器来处理的,组播数据包将发送给网络上组内的所有成员,组播数据包传递的范围由数据包的生存期TTL(TimeToLive)值决定。TTL通过限制IP数据包丢失前通过的路由器数目来决定IP数据包的生存时间,取值范围为0~255。TTL值指定了IP数据包应该传播的范围,IP数据包能够跨过多少个网络,当数据包通过路由器被转发一次,数据包中的TTL值将减1。TTL为0,这个包就被丢弃,不再向前转发;TTL为1时,指定数据包只能发送到本地子网络;TTL为255时,指定数据包能发送到世界范围的所有网站。62数据包的生存期TTL(TimeToLive)组播分组在4.4.2组播Socket类组播Socket类是指组播套接字MulticastSocket类,它是基于数据报套接字DatagramSocket类继承而来的,因此,它也是无连接通信,可使用DatagramSocket类的方法。数据包DatagramPacket类用来存放发送和接收的组播数据包。增加了组播的一些特定功能。634.4.2组播Socket类组播Socket类是指组播套1.MulticastSocke的定义和构造函数定义:publicclassMulticastSocketextendsDatagramSocket构造函数:publicMulticastSocket()throwsIOException:创建组播套接字。publicMulticastSocket(intport)throwsIOException:创建组播套接字并将其绑定到指定端口port。641.MulticastSocke的定义和构造函数定义:pub2.常用方法组播套接字特有的方法:publicInetAddressgetInterface()throwsSocketException:获取用于组播数据包的网络接口的地址。publicvoidsetInterface(InetAddressinf)throwsSocketException:设置组播网络接口,供其行为将受网络接口值影响的方法使用。对多宿主机(multihomedhost)很有用。publicintgetTimeToLive()throwsIOException:获取在套接字上发出的组播数据包的默认生存时间。publicvoidsetTimeToLive(intttl)throwsIOException:设置在此MulticastSocket上发出的组播数据包的默认生存时间,以便控制组播的范围。publicvoidjoinGroup(InetAddressmcastaddr)throwsIOException:加入组播组。publicvoidleaveGroup(InetAddressmcastaddr)throwsIOException:离开组播组。652.常用方法组播套接字特有的方法:65以下3个方法从父类DatagramSocket继承过来的:publicvoidsend(DatagramPacketp)throwsIOException:向组内成员发送数据包,DatagramPacket将包括数据内容、数据长度、目的IP地址和端口的信息。同上抛出异常IOException。TTL值缺省时为1。publicvoidreceive(DatagramPacketp)throwsIOException:从组播套接字接收一个数据包。本方法返回时,数据包p中存放被接收的数据,且数据包中也含有发送地的IP地址和端口号。如果发生IO错误,就抛出异常IOException。publicvoidclose():关闭此组播套接字。还有其他继承的方法,在此不一一列出。组播套接字使用joinGroup()方法加入到一个组播,通过leaveGroup()方法放弃组中的成员资格。使用send()方法发送组播数据包,使用receive()方法接收组播数据包。66以下3个方法从父类DatagramSocket继承过来的:64.4.3组播Socket的实例编写一个Java组播应用程序主要完成如下过程:①创建一个用于发送和接收的MulticastSocket组播套接字对象。②建立一个指定缓冲区大小及组播地址和端口的DatagramPacket组
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年电工电子专业知识
- 2026年保险业招聘笔试仿真题集
- 2026年白山市八道江区环境系统人员招聘考试参考题库及答案解析
- 2026年遥感碳汇笔试高频题精
- 2025江苏如东小洋口文化旅游集团有限公司及子公司招聘7人笔试历年参考题库附带答案详解
- 2025新疆交投独库高速投资发展有限责任公司社会招聘11人笔试历年参考题库附带答案详解
- 2025广西路建工程集团有限公司社会招聘13人笔试历年参考题库附带答案详解
- 2025广东江门市江海区绿信资产管理有限公司招聘3人笔试历年参考题库附带答案详解
- 2025年安徽省四宜控股(集团)有限公司招聘5人笔试历年参考题库附带答案详解
- 2026年二级建造师之二建市政工程实务练习题库包附参考答案详解(培优)
- 《消化系统疾病预防课件》
- 江苏师范大学成人继续教育网络课程《英语》单元测试及参考答案
- 国家职业技能鉴定考评员考试题库
- 马克思主义与社会科学方法论思考题
- 中考英语表格类阅读理解专题
- 城市一卡通系统总体方案
- DL-T 2199-2020 循环流化床锅炉燃料掺烧技术导则
- 糖尿病酮症酸中毒指南精读
- GB/T 11544-2012带传动普通V带和窄V带尺寸(基准宽度制)
- 《绿色建筑概论》整套教学课件
- 主要工业产品统计指南
评论
0/150
提交评论