1 / 64

第十二章 网络程序设计

第十二章 网络程序设计. 浙江工业大学 计算机学院 赵小敏 zxm@zjut.edu.cn http://211.155.231.249:8009. 1. 主要内容. 统一资源定位地址 (URL) 基于 TCP 的网络程序设计 基于 UDP 的网络程序设计 基于 SSL 的网络程序设计. 2. Internet 地址. 在 Internet 上的计算机通过 IP (Internet Protocol) 地址标识 示例 : 216.239.53.100 域名 : www.google.com

orsen
Download Presentation

第十二章 网络程序设计

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第十二章 网络程序设计 浙江工业大学 计算机学院 赵小敏 zxm@zjut.edu.cn http://211.155.231.249:8009 1

  2. 主要内容 统一资源定位地址(URL) 基于TCP的网络程序设计 基于UDP的网络程序设计 基于SSL的网络程序设计 2

  3. Internet地址 在Internet上的计算机通过IP (Internet Protocol)地址标识 示例: 216.239.53.100 域名: www.google.com 类 java.net.InetAddress用来表示Internet地址,它有两个子类,分别是java.net.Inet4Address和java.net.Inet6Address 3

  4. 创建类InetAddress的实例对象 类 InetAddress并不具有public的构造方法 但可以通过下列方法构造: static InetAddress getByAddress(byte[ ] addr) static InetAddress getByName(String host) static InetAddress getLocalHost() 4

  5. 例1:网络地址的例程 • import java.net.InetAddress; • import java.net.UnknownHostException; • public class InetAddressDemo{ • public static void main(String args[]){ • String s = "www.zjut.edu.cn"; • InetAddress zjut= null; • try{ • zjut = InetAddress.getByName(s); • } • catch (UnknownHostException e){ • System.err.println(e); • } • if (ts!=null){ • System.out.println("The IP address of zjut is " • + zjut.getHostAddress( )); • System.out.println("The host name of zjut is " • + zjut.getHostName( )); • } • else System.out.println("Cannot access " + s); • } • }

  6. URL 类 URL 是网络资源定位器(Uniform Resource Locator), 指向网页(World Wide Web) 上的一个资源。 这里的资源可以是文件/目录,也可以是一些复杂的对象,如数据库或搜索引擎(search engine)。 6

  7. URL的格式 (Protocol)(Host)[:Port][File][#Reference] 示例 http://www.ncsa.uiuc.edu:8080/demoweb/urlprimer.html#INSTALL http://211.155.231.249:8009/java http://localhost:8080/index.html#bottom ftp://166.111.233.143/java/ mailto:zxm@zjut.edu.cn 7

  8. 端口号: Port 端口号(Port) 范围: 0-65535 (16 bits)。 小于1024: 用来对应特定的服务 (例如: telnet, SMTP, ftp等等)。 服务端与客户端必须采用相同的端口号。 8

  9. 类: java.net.URL 类java.net.URL的实例对象表示具体的 URL。 public final class URL。 类java.net.URL的中构造方法: public URL(String u) throws MalformedURLException public URL(String protocol, String host, String file) throws MalformedURLException public URL(String protocol, String host, int port, String file) throws MalformedURLException 9

  10. 剖析 URL 类 java.net.URL 具有五个成员方法,可以用来获取URL的五个部分: public String getProtocol( ) public String getHost( ) public int getPort( ) public String getFile( ) public String getRef( ) 10

  11. 例2:解析URL的例程 • import java.net.*; • import java.io.*; • public class ParseURL { • public static void main(String[] args) throws Exception { • URL aURL = new URL("http://java.sun.com:80/docs/books/" • + "tutorial/index.html#DOWNLOADING"); • System.out.println("protocol = " + aURL.getProtocol()); • System.out.println("host = " + aURL.getHost()); • System.out.println("filename = " + aURL.getFile()); • System.out.println("port = " + aURL.getPort()); • System.out.println("ref = " + aURL.getRef()); • } • } 输出结果: protocol = http host = java.sun.com filename = /docs/books/tutorial/index.html port = 80 ref = DOWNLOADING

  12. 从URL读取WWW网络资源 • 当我们得到一个URL对象后,就可以通过它读取指定的WWW资源。这时我们将使用URL的方法openStream(),其定义为:InputStream openStream(); • 方法openSteam()与指定的URL建立连接并返回InputStream类的对象以从这一连接中读取数据。

  13. 读取网络资源数据的一般步骤 • 创建类URL的实力对象,使其指向给定的网络资源; • 通过类URL的成员方法openStream建立URL连接,并返回输入流对象的引用,以便读取数据; • 可选步骤,通过java.io.BufferedInputStream或java.io.BufferedReader封装输入流; • 读取数据,并进行数据处理; • 关闭数据流。

  14. 例3:获取网络资源的例程 • import java.io.*; • import java.net.*; • public class URLReader { • public static void main(String[] args) throws Exception { • URL tirc = new URL("http://www.yahoo.com/"); • BufferedReader in = new BufferedReader(new InputStreamReader(tirc.openStream())); • String inputLine; • File outfile = new File("test.html"); • PrintWriter out = new PrintWriter(new FileWriter(outfile)); • while ((inputLine = in.readLine()) != null) { • //从输入流中不断读取数据直到读完为止 • out.println(inputLine); //把读入的数据写入test.html • } • in.close(); //关闭输入流 • out.close(); • } • }

  15. 主要内容 统一资源定位地址(URL) 基于TCP的网络程序设计 基于UDP的网络程序设计 基于SSL的网络程序设计 15

  16. 传输控制协议TCP 传输控制协议TCP (Transfer Control Protocol) 是一种基于连接的协议,可以在两台计算机之间提供可靠的数据传输。 基于连接的协议,可提供可靠的数据传输 服务器端与客户端通过TCP协议进行通讯 连接通道的两端称为套接字(Socket) 16

  17. 基于TCP的网络数据通信模型 服务器端 ServerSocket(port#) ServerSocket.accept() OutputStream InputStream Socket.close() 客户端 Socket(host, port#) OutputStream InputStream Socket.close() 17

  18. 类 java.net.Socket 类java.net.Socket允许如下的四种基本操作 1. 连接到远程的机器 2. 发送数据 3. 接收数据 4. 关闭连接 18

  19. 类java.net.Socket中的成员方法 构造方法 getInputStream(): 返回该socket所对应的输入流 getOutputStream():返回该socket所对应的输出流 19

  20. 创建类 Socket 的实例对象 构造方法 Socket() Socket(InetAddress address, int port) Socket(InetAddress address, int port, InetAddress localAddr, int localPort) Socket(String host, int port) Socket(String host, int port, InetAddress localAddr, int localPort) 示例: Socket javaSite = new Socket("java.sun.com", 80); 20

  21. 类java.net.ServerSocket ServerSocket类的主要方法 (1) Socket accept() throws IOException 等待客户连接,该方法将阻塞当前系统服务线程,直到连接成功。该方法返回一个套接字类对象,通过该套接字,新的服务子线程与连接的客户进行通信。 (2) Void close() throws IOException 关闭套接字

  22. 怎样用socket进行客户与服务器通信 Socket是两个实体之间进行通信的有效端点。通过Socket可以获得源IP地址和源端口、终点IP地址和终点端口。用户可以将多个socket连入同一个端口,以便对于单个端口可以有多个连接。 通过Socket客户/服务器编程可以创建一个能被许多人使用的分布式程序,并且所有客户均可以用统一的前端进行工作,并与服务器进行通信。

  23. 与服务器通信必须具备三个条件 • 服务器程序 • 客户程序 • 连接它们的Socket程序

  24. ServerSocket类 • 它的实例使服务器能够检测到指定端口的信息 • accept()方法可以使服务器检测到指定端口的活动 • 服务器还负责检测要求与它连接的客户。

  25. Socket类 • getInputStream()和getOutStream()方法来发送和捕捉数据。 try{ //传递给它一个整数作为服务器指定可以使用的给定端口 ServerSocket myServerSocket=new ServerSocket(80); Socket mySocket=myServerSocket.accept(); //检测端口的活动 }catch(Exception e){ }

  26. Socket类 Accept()方法直到接收到用户的连接请求,才继续执行中断的执行程序。一旦客户的连接成功,mySocket就代表该连接,并且可以发送和接收数据。 最后,我们看一看客户是怎样请求连接的。其连接方法如下: try{ Socket mySocket=new Socket("www.yahoo.com",80); }catch(Exception e ){ }

  27. (一)TCP协议通信的服务器方实现 (1) 假设服务器工作在端口8000上, ServerSocket svrsoc= ServerSocket(8000) Socket soc=svrsoc.accept();//监视端口8000的连接请求 (2) 打开与soc绑定的输入/输出流: In=new BufferedReader(new InputStreamRead(soc.getInputStream())); //在套接字soc上绑定的输入流基础上构造BufferedReader对象

  28. TCP协议通信的服务器方实现(续) out=new PrintWrite(new bufferedWrite(new OutputStreamWrite(soc.getOutputStream())),true); //在套接字soc上绑定的输出流基础上构造PrintWrite对象 服务器使用in和out两个实例从客户接收输入信息和向客户程序发信息,同样,在客户端也应该建立这两个对象,用来与服务器程序进行双向通信。

  29. (一) TCP协议通信的服务器方实现(续) (3) 获取客户机的IP地址,并在服务器窗口中显示客户机的地址信息: clientIP=soc.getInetAddress(); System.out.println(“Client’s IP address:”+clientIP); (4) 读入一行客户的输入,并回显该行 String str=in.readLine(); while(!str.equals(“quit”));{ System.out.println(“Client said:”+str); str=in.readLine(); }

  30. (一) TCP协议通信的服务器方实现(续) (5) 不断循环以上代码,直到客户输入“quit”为止。 System.out.println(“Client want to leave.”); finall{ in.close(); out.close(); soc.close(); svrsoc.close(); }

  31. (二)TCP协议通信的客户方实现 (1)创建一个指向固定主机的固定端口的Socket: Socket soc=new Socket(“localhost”,8000); (2) 从Socket对象中获取与其绑定的输入和输出流 In=new BufferedReader(new InputStreamRead(soc.getInputStream())); out=new PrintWrite(new bufferedWrite(new OutputStreamWrite(soc.getOutputStream())),true);

  32. (二)TCP协议通信的客户方实现(续) (3)建立输入/输出流后,从服务器读取发来的”welcome!”信息,显示在窗口: Strin=in.readLine(); System.out.println(“Server said:”+strin);

  33. (二)TCP协议通信的客户方实现(续) (4)客户向服务器发送的数据流从键盘获取 byte bmsg[]=new byte[200]; System.in.read(bmsg); //从键盘读入bmsg String msg=new String(bmsg,0); //byte型转String型 Msg=msg.trim(); //删除msg两边的空格

  34. (二)TCP协议通信的客户方实现(续) (5)当键盘输入不是“quit”时,将键盘输入的数据写入输出流中,并发送出去,然后继续从键盘获取输入数据,不断循环,直到输入“quit”时,先将其传送给服务器,然后关闭输入/输出流和Socket: out.println(strout); In.close(); out.close(); soc.close(); System.exit(0);

  35. 一个简单的客户端/服务器程序 • import java.net.*; • import java.io.*; • import java.lang.*; • public class myserver{ • public static void main(String args[]){ • ServerSocket server; • Socket socket; • String s; • InputStream Is; • OutputStream Os; • DataInputStream DIS; • PrintStream PS; • try{ • server=new ServerSocket(4321); • socket=server.accept(); • System.out.println("server ok"); • System.out.println("************************************************"); • System.out.println("");

  36. Is=socket.getInputStream(); • Os=socket.getOutputStream(); • DIS=new DataInputStream(Is); • PS=new PrintStream(Os); • DataInputStream in=new DataInputStream(System.in); • while(true){ • System.out.println(""); • System.out.println("please wait client's message..."); • System.out.println(""); • s=DIS.readLine(); • System.out.println("client said:"+s); • if(s.trim().equals("BYE"))break; • System.out.print("you say:"); • s=in.readLine(); • PS.println(s); • if(s.trim().equals("BYE"))break; • } • DIS.close(); • PS.close(); • Is.close(); • Os.close(); • socket.close(); • } catch(Exception e){ • System.out.println("Error:"+e); • } //catch • } //main • } //public class

  37. import java.net.*; • import java.io.*; • import java.lang.*; • public class myclient{ • public static void main(String args[]){ • if (args.length<1){ • System.out.println("Please input the Server Name or IP!"); • System.out.println("see also: myclient 127.0.0.1"); • System.exit(1); } //if • Socket socket; • String s=“zxm@zjut.edu.cn"; • String len; • InputStream Is; • OutputStream Os; • DataInputStream DIS; • PrintStream PS; • try{ • socket=new Socket(args[0],4321); • System.out.println("client ok"); • System.out.println("************************************************"); • System.out.println("");

  38. Is=socket.getInputStream(); • Os=socket.getOutputStream(); • DIS=new DataInputStream(Is); • PS=new PrintStream(Os); • DataInputStream in=new DataInputStream(System.in); • while(true){ • System.out.print("you say:"); • s=in.readLine(); • PS.println(s); • if(s.trim().equals("BYE"))break; // • else • { • System.out.println(""); • System.out.println("please wait server's message..."); • System.out.println(""); • } • s=DIS.readLine(); //´ • System.out.println("server said:"+s); • if(s.trim().equals("BYE"))break; } • DIS.close(); // • PS.close(); // • Is.close(); // • Os.close(); // • socket.close(); // • } catch(Exception e){ • System.out.println("Error:"+e); • } • } • }

  39. (三)支持多客户的client/server程序设计 • 在实际应用中,往往是在服务器上运行一个永久的程序,它可以接收来自其他多个客户端的请求,提供相应的服务。 • 利用多线程实现多客户机制:服务器总是在指定的端口上监听是否有客户请求,一旦监听到客户请求,服务器就会启动一个专门的服务线程来响应该客户的请求,而服务器本身在启动完线程之后马上又进入监听状态,等待下一个客户的到来。 • 实现程序包括服务器端主程序、服务器端通信的线程程序和客户端程序

  40. 支持多客户的C/S程序步骤 1、服务器端主程序 (1)创建ServerSocket对象; (2)循环侦听客户端的请求,若监听到客户请求,根据得到的Socket对象和客户端连接数创建服务线程,并启动该线程; (3)关闭ServerSocket对象。

  41. 服务器端程序 • import java.io.*; • import java.net.*; • public class MultiTalkServer{ • static int clientnum=0;//静态成员变量,记录当前客户的个数 • public static void main(String args[ ]) { • ServerSocket serverSocket=null; • boolean listening=true; • try{ • serverSocket=new ServerSocket(4700); • System.out.println("Server is running..."); • //创建一个ServerSocket在端口4700监听客户请求 • }catch(IOException e) { • System.out.println("Could not listen on port:4700."); • System.exit(-1); //退出 • }

  42. 服务器端程序(续) • try{ • while(listening){//永远循环监听 • new ServerThread(serverSocket.accept(),++clientnum).start(); • //监听到客户请求,根据得到的Socket对象和 • //客户计数创建服务线程,并启动之 • System.out.println("Client-"+(clientnum)+" is connected..."); • } • serverSocket.close(); //关闭ServerSocket • }catch(IOException e){ • System.out.println("连接客户端失败"); • } • } • }

  43. 支持多客户的C/S程序步骤(续) 2、服务器端通信的线程程序 (1)定义一个线程类 (2)通过构造方法将服务器端程序传递的Socket对象和客户端连接数赋值给相应的变量 (3)线程体run方法:通过得到的Socket对象获取输入输出流对象,通过循环与客户端发送和接收数据。若循环结束,关闭Socket对象和输入输出流对象

  44. 服务器端通信的线程程序 • import java.io.*; • import java.net.*; • public class ServerThread extends Thread{ • Socket socket=null; //保存与本线程相关的Socket对象 • int clientnum; //保存本进程的客户计数 • public ServerThread(Socket socket,int num) { //构造函数 • this.socket=socket;//初始化socket变量 • clientnum=num+1;//初始化clientnum变量 • } • public void run() {//线程主体 • try{ • String line; • //由Socket对象得到输入流,并构造相应的BufferedReader对象 • BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream())); • //由Socket对象得到输出流,并构造PrintWriter对象 • PrintWriter os=new PrintWriter(socket.getOutputStream()); • //由系统标准输入设备构造BufferedReader对象 • BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));

  45. //在标准输出上打印从客户端读入的字符串 • System.out.println("Client-"+ clientnum +":" +is.readLine()); • //从标准输入读入一字符串 • line=sin.readLine(); • while(!line.equals("bye")){ //如果该字符串为 "bye",则停止循环 • os.println(line); //向客户端输出该字符串 • os.flush(); //刷新输出流,使Client马上收到该字符串 • System.out.println("Server:"+line); • //从Client读入一字符串,并打印到标准输出上 • System.out.println("Client-"+ clientnum +":" +is.readLine()); • line=sin.readLine(); //从系统标准输入读入一字符串 • } //继续循环 • os.close(); //关闭Socket输出流 • is.close(); //关闭Socket输入流 • socket.close(); //关闭Socket • }catch(Exception e){ • System.out.println("Error:"+e); • } • } • }

  46. 支持多客户的C/S程序步骤(续) 3、客户端程序 (1)创建与服务器连接的socket对象 (2) 通过Socket对象获取输入输出流对象,通过循环与客户端发送和接收数据。若循环结束,关闭Socket对象和输入输出流对象。

  47. 客户端程序 • import java.io.*; • import java.net.*; • public class TalkClient { • public static void main(String args[]) { • try{ • //向本机的4700端口发出客户请求 • Socket socket=new Socket("127.0.0.1",4700); • System.out.println("已连接服务器,请发消息给服务器处理..."); • //由系统标准输入设备构造BufferedReader对象 • BufferedReader sin=new BufferedReader(new InputStreamReader(System.in)); • //由Socket对象得到输出流,并构造PrintWriter对象 • PrintWriter os=new PrintWriter(socket.getOutputStream()); • //由Socket对象得到输入流,并构造相应的BufferedReader对象 • BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));

  48. 客户端程序(续) • String readline; • readline=sin.readLine(); //从系统标准输入读入一字符串 • while(!readline.equals("bye")){ //若输入字符串为 "bye"则停止循环 • //将从系统标准输入读入的字符串输出到Server • os.println(readline); • //刷新输出流,使Server马上收到该字符串 • os.flush(); • //在系统标准输出上打印读入的字符串 • System.out.println("Client:"+readline); • //从Server读入一字符串,并打印到标准输出上 • System.out.println("Server:"+is.readLine()); • //从系统标准输入读入一字符串 • readline=sin.readLine(); • } //继续循环 • os.close(); //关闭Socket输出流 • is.close(); //关闭Socket输入流 • socket.close(); //关闭Socket • }catch(Exception e) { • System.out.println("Error"+e); //出错,则打印出错信息 • } • } • }

  49. 课后思考? • 服务器端如何控制客户端的连接数量? • 服务器端如何广播信息给客户端? • 如何实现图形用户界面的C/S聊天系统?

  50. 主要内容 统一资源定位地址(URL) 基于TCP的网络程序设计 基于UDP的网络程序设计 基于SSL的网络程序设计 50

More Related