欢迎来到三一文库! | 帮助中心 三一文库31doc.com 一个上传文档投稿赚钱的网站
三一文库
全部分类
  • 研究报告>
  • 工作总结>
  • 合同范本>
  • 心得体会>
  • 工作报告>
  • 党团相关>
  • 幼儿/小学教育>
  • 高等教育>
  • 经济/贸易/财会>
  • 建筑/环境>
  • 金融/证券>
  • 医学/心理学>
  • ImageVerifierCode 换一换
    首页 三一文库 > 资源分类 > PPT文档下载  

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

    • 资源ID:2159473       资源大小:626.01KB        全文页数:59页
    • 资源格式: PPT        下载积分:8
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录 QQ登录   微博登录  
    二维码
    微信扫一扫登录
    下载资源需要8
    邮箱/手机:
    温馨提示:
    用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP免费专享
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

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

    2019/2/24,1,网络程序设计 Network Programming 第十章 网络通信,赵建立 山东科技大学信息科学与工程学院 College of Information Science and Engineering , Shandong University of Science and Technology zhaojianligmail.com,主要内容,10.1 网络通信简介 10.2 URL通信 10.3 Socket通信 10.4远程方法调用(RMI),10.1 网络通信简介,网络通信的核心是协议。协议是指进程之间交换信息已完成任务所使用的一系列规则和规范。它主要包含两个方面的定义: 1 定义了进程之间交换消息所必需遵循的顺序。 2 定义进程之间所交换的消息的格式。 通过定义协议,可以看出,两个进程只要遵循相同的协议,就可以相互交换信息,而这两个进程可以用不同的编程语言编写,可以位于两个完全不同的计算机上。国际标准化组织给出了一个通用的参考协议,称为开放式系统互连参考模型(ISO/OSI RM)。,图14-1 ISO/OSI RM分层图,主要内容,10.1 网络通信简介 10.2 URL通信 10.3 Socket通信 10.4远程方法调用(RMI),10.2 URL通信,10.2.1 URL简介 10.2.2 URL类 10.2.3 通过字节流访问WWW资源 10.2.4 通过URLConnection实现双向通信 10.2.5使用HttpURLConnection,10.2.1 URL简介,URL用来网络资源定位,它的值由5部分组成,格式如下所示 :/:/ 其中传输协议(protocol)指明获取资源所使用的传输协议,如http、ftp、mms等。主机名(hostname)指定资源所在的计算机,可以是IP地址,如127.0.0.1,也可以是主机名或域名,如www.sun.com。一个计算机中可能有多种服务(应用程序),端口号(port)用来区分不同的网络服务,如http服务的默认端口号是80,ftp服务的默认端口号是21等。文件名(filename)包括该文件的完整路径。在http协议中,缺省的文件名是index.html,因此,,http:/java.sun.com就相等同于 http:/java.sun.com/index.html。引用(reference)为资源内的某个引用,用来定位显示文件内容的位置,如http:/java.sun.com/index.html#chapter1。但并非所有的URL都包含这些元素。对于多数的协议,主机名和文件名是必需的,但端口号和文件内部的引用则是可选的。,10.2 URL通信,10.2.1 URL简介 10.2.2 URL类 10.2.3 通过字节流访问WWW资源 10.2.4通过URLConnection实现双向通信 10.2.5使用HttpURLConnection,10.2.2 URL类,1)URL(String spec),spec为一个完整的URL地址 2) URL(String protocol,String host,int port,String file) 将一个URL地址分解,按不同部分分别指定协议、主机、端口、文件。例如: URL u=new URL(“http”, ”java.sun.com”, 80, “docs/books/tutorial.intro.html”); 3) URL(URL context, String spec) 这种方法基于一个已有的URL对象创建一个新的URL对象,多用于访问同一个主机上不同路径的文件,例如: URL u=new URL(“http:/java.sun.com:80/docs/books/”); URL u1=new URL(u, ”tutorial.intro.html”); URL u2=new URL(u, ”tutorial.super.html”);,【例10-1】URL的使用,import java.io.*; import java.net.*; public class URL1 public static void main(String args) throws IOException URL url = new URL(“http:/www.javajeff.com/articles/articles/html“); System.out.println(“Authority = “ + url.getAuthority(); System.out.println(“Default port = “ + url.getDefaultPort(); System.out.println(“File = “ + url.getFile(); System.out.println(“Host = “ + url.getHost(); System.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.2 URL通信,10.2.1 URL简介 10.2.2 URL类 10.2.3 通过字节流访问WWW资源 10.2.4通过URLConnection实现双向通信 10.2.5使用HttpURLConnection,10.2.3 通过字节流访问WWW资源,URL对象创建后,就可以通过它来访问指定的WWW资源。这时需要调用URL类的openStream()方法,该方法与指定的URL建立连接并返回一个InputStream类的对象,这样访问网络资源的操作就变成了我们熟悉的I/O操作,接下来就可以用字节流的方式读取资源数据。,【例10-2】通过URL对象访问资源,import java.io.*; import java.net.*; public class URL2 public static void main (String args) throws IOException URL url = new URL (“http:/www.javajeff.com/articles/articles/html”); InputStreamReader isr = new InputStreamReader (url.openStream (); BufferedReader br=new BufferedReader(isr); String s; while (s = br.readLine () != null) System.out.print (s); br.close (); ,10.2 URL通信,10.2.1 URL简介 10.2.2 URL类 10.2.3 通过字节流访问WWW资源 10.2.4通过URLConnection实现双向通信 10.2.5 使用HttpURLConnection,10.2.4通过URLConnection实现双向通信,实际应用中,只能读取数据是不够的,很多情况下,我们都需要将一些信息发送到服务器中去,这就要求我们能够实现同网络资源的双向通信,URLConnection类就是用来解决这一问题的。 类URLConnection也是定义在包java.net里,它表示Java程序和URL在网络上的通信连接。当与一个URL建立连接时,首先要在一个URL对象上通过方法openConnection()生成对应的URLConnection对象。URLConnection是以HTTP协议为中心的类,其中很多方法只有在处理HTTP的URL时才起作用。,1.建立连接 URL url=new URL(“http:/www.yahoo.com/”); URLConnection con=url.openConnection(); 2. 向服务器端送数据 PrintStream ps=new PrintStream(con.getOutputStream(); ps.println(string_data); 3. 从服务器读数据 DataInputStream dis=new DataInputStream(con.getInputStream(); dis.readLine();,【例10-3】URLConnection的使用,import java.io.*; import java.net.*; public class ComWithCgi public static void main(String args) throws Exception / 建立指向本地磁盘上cgi的URL对象 URL url = new URL(“http:/java.sun.com/test.cgi”); URLConnection connection = url.openConnection(); connection.setDoOutput(true); PrintStream ps = new PrintStream(connection.getOutputStream(); ps.println(“0123456789“); ps.close(); / 向服务器输出数据 DataInputStream dis = new DataInputStream(connection. getInputStream(); String inputLine; while (inputLine = dis.readLine() != null) System.out.println(inputLine); dis.close();/ 从服务器读数据 ,10.2 URL通信,10.2.1 URL简介 10.2.2 URL类 10.2.3 通过字节流访问WWW资源 10.2.4通过URLConnection实现双向通信 10.2.5 使用HttpURLConnection,10.2.5 使用HttpURLConnection,HttpURLConnection是URLConnection的子类。HttpURLConnection提供了对Http协议的支持,如果所访问的URL地址是一个Http地址,那么就可以使用HttpURLConnection 。例如: URL url=new URL(“http:/www.sohu.com“); HttpURLConnection connection=( HttpURLConnection)url.openConnection(); 但是要注意如果URL地址不是一个http地址,那么就无法用类型转换获取HttpURLConnection的实例。 由于HttpURLConnection是URLConnection的子类,因此HttpURLConnection具有URLConnection的全部public方法,HttpURLConnection的基本用法也与URLConnection相同。,HttpURLConnection独特的方法,public void disconnect(),断开与服务端的连接。 public InputStream getErrorStream(),返回错误流(Error Stream),所谓错误流是指连接失败时服务端返回的有用数据,这些有用数据通常通过错误流返回。例如服务器端返回404错误时(表示所访问的文件无法找到)。 public String getRequestMethod(),返回请求的类型,请求类型包括Get、POST、HEAD、OPTIONS、PUT、DELETE、TRACE。 public int getResponseCode(),返回服务器端响应的状态字,例如200表示OK,401表示Unauthorized。 public String getResponseMessage(),返回服务器端的响应消息,例如“HTTP/1.0 200 OK”或者“HTTP/1.0 404 Not Found”。 public void setRequestMethod(String method),设置请求的类型,请求类型包括Get、POST、HEAD、OPTIONS、PUT、DELETE、TRACE。 public boolean usingProxy(),返回当前HTTP连接是否使用了代理服务器。,主要内容,10.1 网络通信简介 10.2 URL通信 10.3 Socket通信 10.4远程方法调用(RMI),10.3 Socket通信,10.3.1服务器程序 10.3.2 客户机程序 10.3.3 服务多个客户 10.3.4 数据报通信,10.3.1客户-服务器模型,10.3.1服务器程序,服务器的任务就是等候建立一个连接,然后用那个连接产生的Socket 创建一个InputStream 以及一个OutputStream。之后,从InputStream 读入的所有东西都会反馈给OutputStream,直到接收到行中止(END)为止,最后关闭连接。客户机连接与服务器的连接,然后创建一个OutputStream。文本行通过OutputStream 发送。客户机也会创建一个InputStream,用它收听服务器说些什么。服务器与客户机(程序)都使用同样的端口号,而且客户机利用本地主机地址连接位于同一台机器中的服务器(程序),所以不必在一个物理性的网络里完成测试。,注意,ServerSocket 只要一个端口编号,不需要IP 地址(因为它就在这台机器上运行)。调用accept()时,方法暂时陷入停顿状态,直到某个客户尝试同它建立连接。建好一个连接以后,accept()会返回一个Socket对象,它是那个连接的代表。假如ServerSocket 构建器失败,则程序简单地退出(注意必须保证ServerSocket 的构建器在失败之后不会留下任何打开的网络套接字)。针对这种情况,main()会“掷”出一个IOException 违例,所以不必使用一个try 块。若ServerSocket 构建器成功执行,则其他所有方法调用都必须到一个try-finally 代码块里寻求保护,以确保无论块以什么方式留下,ServerSocket 都能正确地关闭。,同样的道理也适用于由accept()返回的Socket。若accept() 失败,那么我们必须保证Socket 不再存在或者含有任何资源,以便不必清除它们。但假若执行成功,则后续的语句必须进入一个try-finally 块内,以保障在它们失败的情况下,Socket 仍能得到正确的清除。由于套接字使用了重要的非内存资源,所以在这里必须特别谨慎,必须自己动手将它们清除。 无论ServerSocket 还是由accept()产生的Socket 都打印到System.out 里。这意味着它们的toString方法会得到自动调用。这样便产生了: ServerSocketaddr=0.0.0.0,PORT=0,localport=8080 Socketaddr=127.0.0.1,PORT=1077,localport=8080 在后面的程序中大家会看到它们如何与客户程序做的事情配合。,程序的下一部分看来似乎仅仅是打开文件,以便读取和写入,只是InputStream 和OutputStream 是从Socket 对象创建的。利用两个“转换器”类InputStreamReader 和OutputStreamWriter ,InputStream 和OutputStream 对象已经分别转换成为Java 1.1 的Reader 和Writer 对象。也可以直接使用Java1.0 的InputStream 和OutputStream 类,但对输出来说,使用Writer 方式具有明显的优势。这一优势是通过PrintWriter 表现出来的,它有一个过载的构建器,能获取第二个参数一个布尔值标志,指向是否在每一次println()结束的时候自动刷新输出(但不适用于print()语句)。每次写入了输出内容后(写进out),它的缓冲区必须刷新,使信息能正式通过网络传递出去。对目前这个例子来说,刷新显得尤,为重要,因为客户和服务器在采取下一步操作之前都要等待一行文本内容的到达。若刷新没有发生,那么信息不会进入网络,除非缓冲区满(溢出),这会为本程序带来许多问题。 编写网络应用程序时,要特别注意自动刷新机制的使用。每次刷新缓冲区时,须创建和发出一个数据包(数据封)。就目前的情况来说,这正是我们所希望的,因为假如包内包含了还没有发出的文本行,服务器和客户机之间的相互联系就会停止。换句话说,一行的末尾就是一条消息的末尾。但在其他许多情况下,消息并不是用行分隔的,所以不如不用自动刷新机制,而用内建的缓冲区判决机制来决定何时发送一个数据包。这样一来,我们可以发出较大的数据包,而且处理进程也能加快。,注意和我们打开的几乎所有数据流一样,它们都要进行缓冲处理。无限while 循环从BufferedReader in 内读取文本行,并将信息写入System.out,然后写入PrintWriter.out。注意这可以是任何数据流,它们只是在表面上同网络连接。客户程序发出包含了“END“的行后,程序会中止循环,并关闭Socket。,【例10-4】Socket通信程序,/ Server_Socket.java import java.io.*; import java.net.*; public class Server_Socket public static final int PORT = 8080; public static void main(String 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 PrintWriter(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.3 Socket通信,10.3.1服务器程序 10.3.2 客户机程序 10.3.3 服务多个客户 10.3.4 数据报通信,例10-4客户程序的源码,import java.net.*; import java.io.*; public class client_socket public static void main(String args)throws IOException InetAddress addr =InetAddress.getByName(null); System.out.println(“addr = “ + addr); Socket socket = new Socket(addr, server_socket.PORT); try ,10.3.2 客户机程序,System.out.println(“socket = “ + socket); BufferedReader in =new BufferedReader( new InputStreamReader(socket.getInputStream(); PrintWriter out =new PrintWriter(new BufferedWriter( new OutputStreamWriter(socket.getOutputStream(),true); for(int i = 0; i 10; i +) out.println(“www “ + i); String str = in.readLine(); System.out.println(str);,10.3.2 客户机程序, out.println(“END“); finally System.out.println(“closing.“); socket.close(); ,输出结果,10.3 Socket通信,10.3.1服务器程序 10.3.2 客户机程序 10.3.3 服务多个客户 10.3.4 数据报通信,10.3.3 服务多个客户,server_socket可以正常工作,但每次只能为一个客户程序提供服务。在服务器中,我们希望同时能处理多个客户的请求。这个问题的关键就是多线程处理机制。对于那些本身不支持多线程的语言,达到这个要求是异常困难的。通过对多线程的学习,大家已经知道Java 已对多线程的处理进行了尽可能的简化。Java 的线程处理方式非常直接,让服务器控制多个客户并不是件难事。最基本的方法是在服务器程序里创建单个ServerSocket,并调用accept()来等候一个新连接。一旦accept()返回,我们就取得结果获得的Socket,并用它新建一个线程,令其只为那个特定的客户服务。然后再调用accept() ,等候下一次新的连接请求。对于下面这段服务器代码,大家可发现它与server_socket.java 例子非常相似,只是为一个特定的客户提供服务的所有操作都已移入一个独立的线程类中。,【例10-5】多客户Socket通信服务端程序,import java.io.*; import java.net.*; class Mult extends Thread private Socket socket; private BufferedReader in; private PrintWriter out; public Mult(Socket s) throws IOException socket = s; in = new BufferedReader( new InputStreamReader(socket.getInputStream(); out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(socket.getOutputStream(), true); start();, public void run() try 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) ,W,/ ServerSoketMult.java public class ServerSoketMult static final int PORT = 8080; public static void main(String args) throws IOException ServerSocket 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 java.net.*; import java.io.*; class ClientSocketMultThread extends Thread private 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.println(“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 (IOException 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-;,/ ClientSocketMult.java import java.io.IOException; import java.net.InetAddress; public class ClientSocketMult static final int MAX_THREADS = 40; public static void main(String args) throws IOException, InterruptedException InetAddress addr = InetAddress.getByName(null); while (true) if (ClientSocketMultThread.threadCount() MAX_THREADS) new ClientSocketMultThread(addr); Thread.sleep(100); ,10.3 Socket通信,10.3.1服务器程序 10.3.2 客户机程序 10.3.3 服务多个客户 10.3.4 数据报通信,10.3.4 数据报通信,前面的例子使用的都是TCP协议。TCP协议具有高度的可靠性,能保证数据顺利抵达目的地。收到字节的顺序与它们发出来时是一样的。不过,TCP协议具有非常高的开销。此外,还有另一种UDP协议,它并不刻意追求数据包会完全发送出去,也不能担保它们抵达的顺序与它们发出时一样。我们认为这是一种“不可靠协议”(TCP 当然是“可靠协议”)。由于它的速度快得多,所以在很多场合是很适用的。 Java 对数据报的支持与它对TCP 套接字的支持大致相同,但也存在一个明显的区别。对数据报来说,我们在客户和服务器程序都可以放置一个DatagramSocket(数据报套接字),但与ServerSocket 不同,前者不会干巴巴地等待建立一个连接的请求。这是由于不再存在“连接”,取而代之的是一个数据报陈列出来。另一项本质的区别的是对TCP 套接字来说,一旦我们建好了连接,便不再需要关心谁向谁“说话”只需通过会话流来回传送数据即可。但对数据报来说,它的数据包必须知道自己来自何处,以及打算去哪里。这意味着我们必须知道每个数据报包的这些信息,否则信息就不能正常地传递。DatagramSocket 用于收发数据包,而DatagramPacket 包含了具体的信息。准备接收一个数据报时,只需提供一个缓冲区,以便安置接收到的数据。数据包抵达时,通过DatagramSocket,作为信息起源地的因特网地址以及端口编号会自动得到初化。,InetAddress类,在描述它们之前,必须了解位于同一个位置的InetAddress类。InetAddress实现了Java.io. Serializable接口,不允许继承。它用于描述和包装一个Internet IP地址,通过三个方法返回InetAddress实例: getLocalhost():返回封装本地地址的实例。getAllByName(String host):返回封装Host地址的InetAddress实例数组。 getByName(String host):返回一个封装Host地址的实例。其中,Host可以是域名或者是一个合法的IP地址。,DatagramSocket类,DatagramSocket类用于创建接收和发送UDP的Socket实例。和Socket类依赖SocketImpl类一样,DatagramSocket类的实现也依靠专门为它设计的DatagramScoketImplFactory类。DatagramSocket类有3个构造函数:DatagramSocket():创建实例。这是个比较特殊的用法,通常用于客户端编程,它并没有特定监听的端口,仅仅使用一个临时的。 DatagramSocket(int port):创建实例,并固定监听Port端口的报文。DatagramSocket(int port, InetAddress localAddr):这是个非常有用的构造函数,当一台机器拥有多于一个IP地址的时候,由它创建的实例仅仅接收来自LocalAddr的报文。,值得注意的是,在创建DatagramSocket类实例时,如果端口已经被使用,会产生一个SocketException的异常抛出,并导致程序非法终止,这个异常应该注意捕获。DatagramSocket类最主要的方法有4个: Receive(DatagramPacket d):接收数据报文到d中。receive方法产生一个“阻塞”。 Send(DatagramPacket d):发送报文d到目的地。 SetSoTimeout(int timeout):设置超时时间,单位为毫秒。 Close():关闭DatagramSocket。在应用程序退出的时候,通常会主动释放资源,关闭Socket,但是由于异常地退出可能造成资源无法回收。所以,应该在程序完成时,主动使用此方法关闭Socket,或在捕获到异常抛出后关闭Socket。,DatagramPacket类,DatagramPacket类用于处理报文,它将Byte数组、目标地址、目标端口等数据包装成报文或者将报文拆卸成Byte数组。应用程序在产生数据包是应该注意,TCP/IP规定数据报文大小最多包含65507个,通常主机接收548个字节,但大多数平台能够支持8192字节大小的报文。DatagramPacket类的构造函数共有4个: DatagramPacket(byte buf, int length, InetAddress addr, int port):从Buf数组中,取出length长的数据创建数据包对象,目标是Addr地址,Port端口。 DatagramPacket(byte buf, int offset, int length, InetAddress address, int port):从Buf数组中,取出Offset开始的、length长的数据创建数据包对象,目标是Addr地址,Port端口。 DatagramPacket(byte buf, int offset, int length):将数据包中从Offset开始、length长的数据装进Buf数组。 DatagramPacket(byte buf, int length):将数据包中length长的数据装进Buf数组。,主要内容,10.1 网络通信简介 10.2 URL通信 10.3 Socket通信 10.4远程方法调用(RMI),10.4远程方法调用(RMI),RMI使运行在同一台计算机上的Java对象可以通过远程方法调用来进行通信.这些方法调用和对同一程序中对象的操作是一样的.在面向过程的语言中实现类似功能的是远程过程调用RPC(Remote Procedure Call), RPC使得程序可以方便的调用另一个计算机上的函数,就像调用本机上的函数一样方便,这样就可以使程序员从复杂的网络通信中解脱出来从而集中精力于应用程序的其他工作.当然RPC有自己的缺点,首先RPC采用中性语言实现,并且返回的是用外部数据表示的值,对数据表示协议依赖很强,很难应用到面向对象分布计算系统中。而远程调用方法RMI(Remote Method Invocation)实质上模拟了应用在分布计算系统中的RPC,使用Java远程信息交换协议JR

    注意事项

    本文(网络程序设计(java)第10章网络通信.ppt)为本站会员(本田雅阁)主动上传,三一文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知三一文库(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    经营许可证编号:宁ICP备18001539号-1

    三一文库
    收起
    展开