网络程序设计(java)第10章网络通信

上传人:人*** 文档编号:584261467 上传时间:2024-08-30 格式:PPT 页数:59 大小:452.50KB
返回 下载 相关 举报
网络程序设计(java)第10章网络通信_第1页
第1页 / 共59页
网络程序设计(java)第10章网络通信_第2页
第2页 / 共59页
网络程序设计(java)第10章网络通信_第3页
第3页 / 共59页
网络程序设计(java)第10章网络通信_第4页
第4页 / 共59页
网络程序设计(java)第10章网络通信_第5页
第5页 / 共59页
点击查看更多>>
资源描述

《网络程序设计(java)第10章网络通信》由会员分享,可在线阅读,更多相关《网络程序设计(java)第10章网络通信(59页珍藏版)》请在金锄头文库上搜索。

1、2024/8/301网络程序设计网络程序设计Network Programming第十章第十章 网络通信网络通信赵建立赵建立山东科技大学信息科学与工程学院山东科技大学信息科学与工程学院College of Information Science and Engineering , Shandong University of Science and Technology主要内容10.1网络通信简介10.2URL通信10.3Socket通信远程方法调用(RMI)10.1网络通信简介网络通信的核心是协议。协议是指进程之间交换信息已完成任务所使用的一系列规则和规范。它主要包含两个方面的定义:1定义了

2、进程之间交换消息所必需遵循的顺序。2定义进程之间所交换的消息的格式。通过定义协议,可以看出,两个进程只要遵循相同的协议,就可以相互交换信息,而这两个进程可以用不同的编程语言编写,可以位于两个完全不同的计算机上。国际标准化组织给出了一个通用的参考协议,称为开放式系统互连参考模型(ISO/OSIRM)。图14-1ISO/OSIRM分层图主要内容10.1网络通信简介10.2URL通信10.3Socket通信远程方法调用(RMI)10.2URL通信10.2.1URL简介10.2.2URL类10.2.3通过字节流访问WWW资源10.2.4通过URLConnection实现双向通信使用HttpURLCon

3、nection10.2.1URL简介URL用来网络资源定位,它的值由5部分组成,格式如下所示:/:/其中传输协议(protocol)指明获取资源所使用的传输协议,如http、ftp、mms等。主机名(hostname)指定资源所在的计算机,可以是IP地址,如,也可以是主机名或域名,如。一个计算机中可能有多种服务(应用程序),端口号(port)用来区分不同的网络服务,如http服务的默认端口号是80,ftp服务的默认端口号是21等。文件名(filename)包括该文件的完整路径。在http协议中,缺省的文件名是,因此,就相等同于。引用(reference)为资源内的某个引用,用来定位显示文件内容

4、的位置,如http:/ java.io.*;import .*;public class URL1public static void main(String args) throws IOExceptionURL url = new URL(http:/ = + url.getAuthority();System.out.println(Default port = + url.getDefaultPort();System.out.println(File = + url.getFile();System.out.println(Host = + url.getHost();System.

5、out.println(Path = + url.getPath();System.out.println(Port = + url.getPort();System.out.println(Protocol = + url.getProtocol();System.out.println(Query = + url.getQuery();System.out.println(Ref = + url.getRef();System.out.println(User Info = + url.getUserInfo();101运行结果10.2URL通信10.2.1URL简介10.2.2URL类1

6、0.2.3通过字节流访问WWW资源通过URLConnection实现双向通信使用HttpURLConnection10.2.3通过字节流访问WWW资源URL对象创建后,就可以通过它来访问指定的WWW资源。这时需要调用URL类的openStream()方法,该方法与指定的URL建立连接并返回一个InputStream类的对象,这样访问网络资源的操作就变成了我们熟悉的I/O操作,接下来就可以用字节流的方式读取资源数据。【例10-2】通过URL对象访问资源importjava.io.*;.*;publicclassURL2publicstaticvoidmain(Stringargs)throwsI

7、OExceptionURLurl=newURL(“”);InputStreamReaderisr=newInputStreamReader(url.openStream();BufferedReaderbr=newBufferedReader(isr);Strings;while(s=br.readLine()!=null)System.out.print(s);br.close();10.2URL通信10.2.1URL简介10.2.2URL类10.2.3通过字节流访问WWW资源通过URLConnection实现双向通信10.2.5使用HttpURLConnection通过URLConnect

8、ion实现双向通信实际应用中,只能读取数据是不够的,很多情况下,我们都需要将一些信息发送到服务器中去,这就要求我们能够实现同网络资源的双向通信,URLConnection类就是用来解决这一问题的。类URLConnection也是定义在包里,它表示Java程序和URL在网络上的通信连接。当与一个URL建立连接时,首先要在一个URL对象上通过方法openConnection()生成对应的URLConnection对象。URLConnection是以HTTP协议为中心的类,其中很多方法只有在处理HTTP的URL时才起作用。1.建立连接URLurl=newURL(“”);URLConnectionco

9、n=url.openConnection();2.向服务器端送数据PrintStreamps=newPrintStream(con.getOutputStream();ps.println(string_data);3.从服务器读数据DataInputStreamdis=newDataInputStream(con.getInputStream();dis.readLine();【例10-3】URLConnection的使用import java.io.*;import .*;public class ComWithCgipublic static void main(String args)

10、 throws Exception / 建立指向本地磁盘上cgi的URL对象URL url = new URL(“http:/ URLConnection connection = url.openConnection();connection.setDoOutput(true);PrintStream ps = new PrintStream(connection.getOutputStream();ps.println(0123456789);ps.close(); / 向服务器输出数据DataInputStream dis = new DataInputStream(connection

11、. getInputStream();String inputLine;while (inputLine = dis.readLine() != null) System.out.println(inputLine);dis.close();/ 从服务器读数据10.2URL通信10.2.1URL简介10.2.2URL类10.2.3通过字节流访问WWW资源通过URLConnection实现双向通信10.2.5使用HttpURLConnection10.2.5使用HttpURLConnectionHttpURLConnection是URLConnection的子类。HttpURLConnectio

12、n提供了对Http协议的支持,如果所访问的URL地址是一个Http地址,那么就可以使用HttpURLConnection。例如:URLurl=newURL(http:/);HttpURLConnectionconnection=(HttpURLConnection)url.openConnection();但是要注意如果URL地址不是一个http地址,那么就无法用类型转换获取HttpURLConnection的实例。由于HttpURLConnection是URLConnection的子类,因此HttpURLConnection具有URLConnection的全部public方法,HttpURL

13、Connection的基本用法也与URLConnection相同。HttpURLConnection独特的方法publicvoiddisconnect(),断开与服务端的连接。publicInputStreamgetErrorStream(),返回错误流(ErrorStream),所谓错误流是指连接失败时服务端返回的有用数据,这些有用数据通常通过错误流返回。例如服务器端返回404错误时(表示所访问的文件无法找到)。publicStringgetRequestMethod(),返回请求的类型,请求类型包括Get、POST、HEAD、OPTIONS、PUT、DELETE、TRACE。publici

14、ntgetResponseCode(),返回服务器端响应的状态字,例如200表示OK,401表示Unauthorized。publicStringgetResponseMessage(),返回服务器端的响应消息,例如“HTTP/1.0200OK”或者“HTTP/1.0404NotFound”。publicvoidsetRequestMethod(Stringmethod),设置请求的类型,请求类型包括Get、POST、HEAD、OPTIONS、PUT、DELETE、TRACE。publicbooleanusingProxy(),返回当前HTTP连接是否使用了代理服务器。主要内容10.1网络通信

15、简介10.2URL通信10.3Socket通信远程方法调用(RMI)10.3Socket通信服务器程序10.3.2客户机程序10.3.3服务多个客户10.3.4数据报通信客户-服务器模型服务器程序服务器的任务就是等候建立一个连接,然后用那个连接产生的Socket创建一个InputStream以及一个OutputStream。之后,从InputStream读入的所有东西都会反馈给OutputStream,直到接收到行中止(END)为止,最后关闭连接。客户机连接与服务器 的 连 接 , 然 后 创 建 一 个 OutputStream。 文 本 行 通 过OutputStream发送。客户机也会创

16、建一个InputStream,用它收听服务器说些什么。服务器与客户机(程序)都使用同样的端口号,而且客户机利用本地主机地址连接位于同一台机器中的服务器(程序),所以不必在一个物理性的网络里完成测试。注意,ServerSocket只要一个端口编号,不需要IP地址(因为它就在这台机器上运行)。调用accept()时,方法暂时陷入停顿状态,直到某个客户尝试同它建立连接。建好一个连接以后,accept()会 返 回 一 个 Socket对 象 , 它 是 那 个 连 接 的 代 表 。 假 如ServerSocket构建器失败,则程序简单地退出(注意必须保证ServerSocket的构建器在失败之后不

17、会留下任何打开的网络套接字)。针对这种情况,main()会“掷”出一个IOException违例,所以不必使用一个try块。若ServerSocket构建器成功执行,则其他所有方法调用都必须到一个try-finally代码块里寻求保护,以确保无论块以什么方式留下,ServerSocket都能正确地关闭。同样的道理也适用于由accept()返回的Socket。若accept()失败,那么我们必须保证Socket不再存在或者含有任何资源,以便不必清除它们。但假若执行成功,则后续的语句必须进入一个try-finally块内,以保障在它们失败的情况下,Socket仍能得到正确的清除。由于套接字使用了重

18、要的非内存资源,所以在这里必须特别谨慎,必须自己动手将它们清除。无 论 ServerSocket 还 是 由 accept()产 生 的 Socket 都 打 印 到System.out里。这意味着它们的toString方法会得到自动调用。这样便产生了:ServerSocketaddr=0.0.0.0,PORT=0,localport=8080Socketaddr=127.0.0.1,PORT=1077,localport=8080在后面的程序中大家会看到它们如何与客户程序做的事情配合。程序的下一部分看来似乎仅仅是打开文件,以便读取和写入,只是InputStream 和OutputStream

19、 是从Socket 对象创建的。利用两个“转换器”类InputStreamReader 和OutputStreamWriter ,InputStream 和OutputStream 对象已经分别转换成为 的Reader 和Writer 对象。也可以直接使用 的InputStream 和OutputStream 类,但对输出来说,使用Writer 方式具有明显的优势。这一优势是通过PrintWriter 表现出来的,它有一个过载的构建器,能获取第二个参数一个布尔值标志,指向是否在每一次println()结束的时候自动刷新输出(但不适用于print()语句)。每次写入了输出内容后(写进out),它

20、的缓冲区必须刷新,使信息能正式通过网络传递出去。对目前这个例子来说,刷新显得尤为重要,因为客户和服务器在采取下一步操作之前都要等待一行文本内容的到达。若刷新没有发生,那么信息不会进入网络,除非缓冲区满(溢出),这会为本程序带来许多问题。编写网络应用程序时,要特别注意自动刷新机制的使用。每次刷新缓冲区时,须创建和发出一个数据包(数据封)。就目前的情况来说,这正是我们所希望的,因为假如包内包含了还没有发出的文本行,服务器和客户机之间的相互联系就会停止。换句话说,一行的末尾就是一条消息的末尾。但在其他许多情况下,消息并不是用行分隔的,所以不如不用自动刷新机制,而用内建的缓冲区判决机制来决定何时发送一

21、个数据包。这样一来,我们可以发出较大的数据包,而且处理进程也能加快。注意和我们打开的几乎所有数据流一样,它们都要进行缓冲处理。无限while循环从BufferedReaderin内读取文本行,并将信息写入,然后写入。注意这可以是任何数据流,它们只是在表面上同网络连接。客户程序发出包含了END的行后,程序会中止循环,并关闭Socket。【例10-4】Socket通信程序import java.io.*;import .*;public class Server_Socket public static final int PORT = 8080;public static void main(S

22、tring args) throws IOException ServerSocket s = new ServerSocket(PORT);System.out.println(Started: + s);try Socket socket = s.accept();try System.out.println(Connection accepted: + socket);BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream();PrintWriter out = new Prin

23、tWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), true);while (true) String str = in.readLine();if (str.equals(END)break;System.out.println(Echoing: + str);out.println(str + str + haha); finally System.out.println(closing.); socket.close(); finally s.close();10.3Socket通信服务器

24、程序10.3.2客户机程序10.3.3服务多个客户10.3.4数据报通信例10-4客户程序的源码.*;importjava.io.*;publicclassclient_socketpublicstaticvoidmain(Stringargs)throwsIOExceptionInetAddressaddr=InetAddress.getByName(null);System.out.println(addr=+addr);Socketsocket=newSocket(addr,server_socket.PORT);try10.3.2客户机程序System.out.println(sock

25、et=+socket);BufferedReaderin=newBufferedReader(newInputStreamReader(socket.getInputStream();PrintWriterout=newPrintWriter(newBufferedWriter(newOutputStreamWriter(socket.getOutputStream(),true);for(inti=0;i10;i+)out.println(www+i);Stringstr=in.readLine();System.out.println(str);10.3.2客户机程序out.println

26、(END);finallySystem.out.println(closing.);socket.close();输出结果10.3Socket通信服务器程序10.3.2客户机程序10.3.3服务多个客户10.3.4数据报通信10.3.3服务多个客户server_socket可以正常工作,但每次只能为一个客户程序提供服务。在服务器中,我们希望同时能处理多个客户的请求。这个问题的关键就是多线程处理机制。对于那些本身不支持多线程的语言,达到这个要求是异常困难的。通过对多线程的学习,大家已经知道Java已对多线程的处理进行了尽可能的简化。Java的线程处理方式非常直接,让服务器控制多个客户并不是件难事

27、。最基本的方法是在服务器程序里创建单个ServerSocket,并调用accept()来等候一个新连接。一旦accept()返回,我们就取得结果获得的Socket,并用它新建一个线程,令其只为那个特定的客户服务。然后再调用accept(),等候下一次新的连接请求。对于下面这段服务器代码,大家可发现它与server_socket.java例子非常相似,只是为一个特定的客户提供服务的所有操作都已移入一个独立的线程类中。【例10-5】多客户Socket通信服务端程序import java.io.*;import .*;class Mult extends Threadprivate Socket s

28、ocket;private BufferedReader in;private PrintWriter out;public Mult(Socket s) throws IOExceptionsocket = s;in = new BufferedReader(new InputStreamReader(socket.getInputStream();out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), true);start();public void run()tr

29、y while (true) String str = in.readLine();if (str.equals(END)break;System.out.println(Echoing: + str);out.println(str);System.out.println(closing.); catch (IOException e) finally try socket.close(); catch (IOException e) Wpublic class ServerSoketMultstatic final int PORT = 8080;public static void ma

30、in(String args) throws IOExceptionServerSocket s = new ServerSocket(PORT);System.out.println(Server Started);try while (true) Socket socket = s.accept();try new mult(socket); catch (IOException e) socket.close(); finally s.close();【例10-6】多客户Socket通信客户端程序import .*;import java.io.*;class ClientSocketM

31、ultThread extends Threadprivate Socket socket;private BufferedReader in;private PrintWriter out;private static int counter = 0;private int id = counter+;private static int threadcount = 0;public static int threadCount()return threadcount; public ClientSocketMultThread(InetAddress addr)System.out.pri

32、ntln(Making client + id);threadcount+;try socket = new Socket(addr, ServerSoketMult.PORT); catch (IOException e) try in = new BufferedReader(new InputStreamReader(socket.getInputStream();out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), true);start(); catch (I

33、OException e) try socket.close(); catch (IOException e2) public void run()try for (int i = 0; i 25; i+) out.println(Client + id + : + i);String str = in.readLine();System.out.println(str);out.println(END); catch (IOException e) finally try socket.close(); catch (IOException e) threadcount-;import ja

34、va.io.IOException;import .InetAddress;public class ClientSocketMultstatic final int MAX_THREADS = 40;public static void main(String args) throws IOException,InterruptedExceptionInetAddress addr = InetAddress.getByName(null);while (true) if (ClientSocketMultThread.threadCount() MAX_THREADS)new Client

35、SocketMultThread(addr);Thread.sleep(100);10.3Socket通信服务器程序10.3.2客户机程序10.3.3服务多个客户10.3.4数据报通信10.3.4数据报通信前面的例子使用的都是TCP协议。TCP协议具有高度的可靠性,能保证数据顺利抵达目的地。收到字节的顺序与它们发出来时是一样的。不过,TCP协议具有非常高的开销。此外,还有另一种UDP协议,它并不刻意追求数据包会完全发送出去,也不能担保它们抵达的顺序与它们发出时一样。我们认为这是一种“不可靠协议”(TCP 当然是“可靠协议”)。由于它的速度快得多,所以在很多场合是很适用的。Java 对数据报的支

36、持与它对TCP 套接字的支持大致相同,但也存在一个明显的区别。对数据报来说,我们在客户和服务器程序都可以放置一个DatagramSocket(数据报套接字),但与ServerSocket 不同,前者不会干巴巴地等待建立一个连接的请求。这是由于不再存在“连接”,取而代之的是一个数据报陈列出来。另一项本质的区别的是对TCP 套接字来说,一旦我们建好了连接,便不再需要关心谁向谁“说话”只需通过会话流来回传送数据即可。但对数据报来说,它的数据包必须知道自己来自何处,以及打算去哪里。这意味着我们必须知道每个数据报包的这些信息,否则信息就不能正常地传递。DatagramSocket 用于收发数据包,而Da

37、tagramPacket 包含了具体的信息。准备接收一个数据报时,只需提供一个缓冲区,以便安置接收到的数据。数据包抵达时,通过DatagramSocket,作为信息起源地的因特网地址以及端口编号会自动得到初化。InetAddress类在描述它们之前,必须了解位于同一个位置的InetAddress类。InetAddress实现了Java.io.Serializable接口,不允许继承。它用于描述和包装一个InternetIP地址,通过三个方法返回InetAddress实例:getLocalhost():返回封装本地地址的实例。getAllByName(Stringhost):返回封装Host地址

38、的InetAddress实例数组。getByName(Stringhost):返回一个封装Host地址的实例。其中,Host可以是域名或者是一个合法的IP地址。DatagramSocket类DatagramSocket类用于创建接收和发送UDP的Socket实例。和Socket类依赖SocketImpl类一样,DatagramSocket类的实现也依靠专门为它设计的DatagramScoketImplFactory类。DatagramSocket类有3个构造函数:DatagramSocket():创建实例。这是个比较特殊的用法,通常用于客户端编程,它并没有特定监听的端口,仅仅使用一个临时的。D

39、atagramSocket(intport):创建实例,并固定监听Port端口的报文。DatagramSocket(intport,InetAddresslocalAddr):这是个非常有用的构造函数,当一台机器拥有多于一个IP地址的时候,由它创建的实例仅仅接收来自LocalAddr的报文。值得注意的是,在创建DatagramSocket类实例时,如果端口已经被使用,会产生一个SocketException的异常抛出,并导致程序非法终止,这个异常应该注意捕获。DatagramSocket类最主要的方法有4个:Receive(DatagramPacketd):接收数据报文到d中。receive方

40、法产生一个“阻塞”。Send(DatagramPacketd):发送报文d到目的地。SetSoTimeout(inttimeout):设置超时时间,单位为毫秒。Close():关闭DatagramSocket。在应用程序退出的时候,通常会主动释放资源,关闭Socket,但是由于异常地退出可能造成资源无法回收。所以,应该在程序完成时,主动使用此方法关闭Socket,或在捕获到异常抛出后关闭Socket。DatagramPacket类DatagramPacket类用于处理报文,它将Byte数组、目标地址、目标端口等数据包装成报文或者将报文拆卸成Byte数组。应用程序在产生数据包是应该注意,TCP/

41、IP规定数据报文大小最多包含65507个,通常主机接收548个字节,但大多数平台能够支持8192字节大小的报文。DatagramPacket类的构造函数共有4个:DatagramPacket(bytebuf,intlength,InetAddressaddr,intport):从Buf数组中,取出length长的数据创建数据包对象,目标是Addr地址,Port端口。DatagramPacket(bytebuf,intoffset,intlength,InetAddressaddress,intport):从Buf数组中,取出Offset开始的、length长的数据创建数据包对象,目标是Addr

42、地址,Port端口。DatagramPacket(bytebuf,intoffset,intlength):将数据包中从Offset开始、length长的数据装进Buf数组。DatagramPacket(bytebuf,intlength):将数据包中length长的数据装进Buf数组。主要内容10.1网络通信简介10.2URL通信10.3Socket通信远程方法调用(RMI)远程方法调用(RMI)RMI使运行在同一台计算机上的Java对象可以通过远程方法调用来进行通信.这些方法调用和对同一程序中对象的操作是一样的.在面向过程的语言中实现类似功能的是远程过程调用RPC(Remote Proce

43、dure Call), RPC使得程序可以方便的调用另一个计算机上的函数,就像调用本机上的函数一样方便,这样就可以使程序员从复杂的网络通信中解脱出来从而集中精力于应用程序的其他工作.当然RPC有自己的缺点,首先RPC采用中性语言实现,并且返回的是用外部数据表示的值,对数据表示协议依赖很强,很难应用到面向对象分布计算系统中。而远程调用方法RMI(Remote Method Invocation)实质上模拟了应用在分布计算系统中的RPC,使用Java远程信息交换协议JRMP(Java Remote Messaging Protocol)进行通信,而JRMP是专为Java的远程对象通信制定的协议。因

44、此,RMI就具有Java的可移植性,是分布应用的纯Java解决方案,更具有面向对象的特征。 RPC的另一个缺点是,它要求程序员掌握一种 专 门 的 接 口 定 义 语 言 (Interface Definition language, IDL)来描述可以被远程调用的函数.而RMI不要求程序员学习IDL语言,因为所有的网络连接代码都是从程序已有的类中直接生成的.由于RMI只支持Java一种语言,所以不需要中介语言的IDL,Java自己的接口就已经足够了.RMI具有以下优点面向对象:RMI可将完整的对象作为参数和返回值进行传递,而不仅仅是预定义的数据类型。也就是说,可以将类似Java哈西表这样的复

45、杂类型作为一个参数进行传递。可移动属性:RMI可将属性从客户机移动到服务器,或者从服务器移动到客户机。设计方式:对象传递功能使您可以在分布式计算中充分利用面向对象技术的强大功能,如二层和三层结构系统.如果用户能够传递属性,那么就可以在自己的解决方案中使用面向对象的设计方式。所有面向对象的设计方式无不依靠不同的属性来发挥功能,如果不能传递完整的对象就会失去设计方式上所提供的优点。安全性:RMI使用Java内置的安全机制保证下载执行程序时用户系统的安全。RMI使用专门为保护系统免遭恶意小程序侵害而设计的安全管理程序。便于编写和使用:RMI使得Java远程服务程序和访问这些服务程序的Java客户程序的编写工作变得轻松、简单。

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 高等教育 > 研究生课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号