• 1. 第8章 Java的网络编程 (时间:3次课,6学时)
  • 2. 第8章 Java的网络编程 教学提示:Java语言已成为网络应用软件开发的主要工具。使用Java语言进行网络连接编程比C++语言要容易得多。Java提供了许多内置的网络功能,使开发基于Internet和Web的应用程序更容易。 本章主要介绍:网络基础知识、Socket套接字、Java开发TCP/IP程序、多线程服务器、数据报、URL资源
  • 3. 第8章 Java的网络编程 8.1 网络基础知识 8.2 Socket套接字 8.3 Java开发TCP/IP程序 8.4 多线程服务器 8.5 数据报 8.6 URL资源 8.7 网络聊天程序实例 8.8 课后练习
  • 4. 8.1 网络基础知识 8.1.1 TCP/lP参考模型 8.1.2 建立网络连接
  • 5. 8.1 网络基础知识 网络编程涉及客户与服务器两个方面及它们之间的联系。客户端请求服务器执行某个操作,服务器执行这个操作并对客户端作出响应。在网页浏览器与http 服务器之间,按照请求应答响应模式工作。当用户在浏览器中选定一个网站时,这个请求就发送到相应的网络服务器上。服务器发送相应的HTML网页来响应客户端。
  • 6. 8.1.1 TCP/lP参考模型 TCP/IP是传输控制协议/网际协议的简称,它包含100多个不同功能的协议,是互联网上的通信规则。其中最主要的是TCP 和IP协议。TCP/IP是一个四层的体系结构,它包含应用层、传输层、网际层和网络接口层。
  • 7. 8.1.1 TCP/lP参考模型 按照网络通信的不同层次,Java提供的网络功能有4大类:URL、Sockets、Datagram和InetAddress。应用层负责将网络传输的信息转换成我们能够识别的信息,包括很多面向应用的协议,如SMTP(简单邮件传输协议)、HTTP(超文本传输协议)等。在这一层,Java使用URL、URLConnection 类。通过URL 类,Java程序可以直接发出或读取网络上的数据。传输层提供端到端的通信,包括面向连接的TCP(传输控制协议)和无连接的UDP(用户数据包协议)。TCP协议提供了可靠的数据传输服务,具有流量控制、拥塞控制、按顺序递交等功能。UDP增加的服务是不可靠的,但其系统资源开销小,在流媒体系统中使用较多。
  • 8. 8.1.2 建立网络连接 TCP/IP 中的端口号是一个16 位的数字,它的范围是0~65535。其中的0~1023为系统所保留,专门用于那些通用的服务(例如TELNET、SMTP 和FTP 等),如HTTP 服务的端口号为80,TELNET服务的端口号为21,FTP 服务的端口号为23。因此,编写通信程序时,应选择一个大于1023 的数作为端口号,以免发生冲突。IP地址与端口号组合可以完全分辨Internet 上某台计算机运行的某一程序。 客户和服务器必须事先约定所使用的端口。如果系统两部分所使用的端口不一致,则不能进行通信。客户端与服务器端建立连接的过程如图8-2 所示。
  • 9. 8.1.2 建立网络连接 图8-2 客户端与网络的连接过程
  • 10. 8.1.2 建立网络连接 服务器端软件在远程计算机上连续不断地运行,监听各端口上的通信请求。当服务器上接收到一个对某一端口的连接请求时,就唤醒正在运行的服务器软件,建立连接。该连接将一直保持下去,直到通信的某一方将它中断。
  • 11. 8.2 Socket套接字 Socket(套接字)是网络上运行的两个程序之间双向通信链路的终端点,它是TCP和UDP的基础。一个Socket 被绑定到一个端口号上,这样传输层就能识别数据要发送哪个应用程序。 建立网络连接之后,使用与Socket 相关联的流和使用其他流非常相似。基于Socket的通信通过Socket 读取和写入数据,使应用程序对网上数据的读写操作,像对本地文件的读写一样简单。Socket 允许程序把网络连接当成一个流,可以向这个流写字节,也可以从这个流读取字节。
  • 12. 8.2 Socket套接字 Java 提供了Stream Sockets(流套接字)和Datagram Sockets(数据报套接字)。用Stream Sockets 可以在两个进程之间建立一个连接,连接建立后,数据在相互连接的进程间流动。所以说Stream Sockets 提供面向连接的服务,它使用的是TCP 协议。 在Java编程语言中,TCP/IP Socket 连接是用java.net包中的类实现的。图8-3 说明了Socket 连接机制。
  • 13. 8.2 Socket套接字 图8-3 Socket连接机制
  • 14. 8.2 Socket套接字Socket工程的通信过程如下。 (1) 建立连接:服务器端程序分配一个端口号,开始监听来自客户端的请求。当客户请求一个连接时,服务器使用accept()方法打开Socket 连接,将该Socket 连接到此端口上。 (2) 数据通信:服务器和客户端使用Socket 的InputStream(输入流)和OutputStream(输出流)进行通信。 (3) 关闭连接:通信结束,服务器和客户端程序断开连接,释放所占用的系统资源。
  • 15. 8.3 Java开发TCP/IP程序 Java所提供的网络功能可大致分为如下4大类。 InetAddress:在网络层,用于标识网络上的硬件资源。 URL 和URLConnection:可表示和建立确定网络上资源的位置,Java程序可以直接读入网络上的数据,或把自己的数据传送到网络的另一端。 Socket:是两个不同的程序之间在网络上传输数据的通道,这是网络程序中最基本的方法。一般在TCP/IP协议下的客户服务器软件采用Socket 作为交互方式。 Datagram:是功能最低级的一种。其他网络数据传送方式,都假想在程序执行时,建立一条安全稳定的通道。但是以Datagram 方式传送数据时,只把数据目的地记录在数据包中,然后就直接放在网络上进行传输,系统不保证数据一定能够安全送到,也不能确定什么时候可以送到。
  • 16. 8.4 多线程服务器 8.4.1 服务器端ServerSocket 8.4.2 客户端Socket 8.4.3 多线程服务器实例
  • 17. 8.4 多线程服务器 Java软件包内在支持的网络协议为TCP/IP,也是当今最流行的广域网/局域网协议。Java有关网络的类及接口定义在java.net包中。客户端软件通常使用java.net包中的核心类Socket与服务器的某个端口建立连接,而服务器程序不同于客户机,它需要初始化一个端口进行监听,遇到连接呼叫,才与相应的客户机建立连接。
  • 18. 8.4.1 服务器端ServerSocket 在ServerSocket 类中包含了创建ServerSocket 对象的构造方法、在指定端口监听的方法、建立连接后发送和接收数据的方法。 构造方法如下: public ServerSocket(int port) throws IOException BindExceptio public ServerSocket(int port, int queuelength) throws IOException, BindException public ServerSocket(int port, int queuelength, InetAddress bindaddress) throws IOException, BindException
  • 19. 8.4.1 服务器端ServerSocketServerSocket 类的常用方法有以下几个。 public Socket accept() throws IOException public void close() throws IOException public InetAddress get InetAddress() public int getLocalPort()
  • 20. 8.4.2 客户端Socket 客户端Socket的构造函数如下。 (1) public Socket(String host,int port) throws unknownHostException, IOException 这个方法建立一个到主机host、端口号为port 的套接字,连接到远程主机。示范代码如下。 try { Socket soc=new Socket("www.sun.com",80); //发送数据 } catch(unknownHostException uex) { } catch(IOException e) { } (2) public Socket(InetAddress host,int port) throws IOException 建立一个套接字,与前一个不同的是,它用InetAddress 对象指定套接字。如果出错则抛出IOException 异常。
  • 21. 8.4.2 客户端Socket Socket类的常用方法有以下几个。 (1) public InetAddress getInetAddress() 调用Socket 对象的getInetAddress()方法返回连接到远程主机的地址,如果连接失败,则返回以前连接的主机。 (2) public int getPort() 返回Socket连接的远程主机端口号。 (3) public int getLocalPort() 一个Socket 连接两个终端,方法getLocalPort()返回本地连接终端的端口号。
  • 22. 8.4.2 客户端Socket (4) public InetAddress getLocalAddress() 此方法告诉用户套接字Socket 绑定到哪个网络接口。用户通常在多目录的主机或带有多目录的网络接口上使用这个方法。 (5) public InputStream getInputStream() throws IOException 这个方法返回一个输入流,利用这个流就可以从套接字读取数据。通常连接这个流到一个BufferedInputStream 或者BufferedReader。
  • 23. 8.4.2 客户端Socket(6) public OutputStream getOutputStream() throws IOException 返回一个原始的Outputstream,可以从应用程序写数据到套接字的另一端。通常将它连接到DataOutputStream 或者OutputStreamWriter 等更方便的类,还可以连接到缓冲类。 (7) public synchronized void close() throws IOException 虽然套接字会在程序结束时被自动关闭,但是应该用close()方法断开连接,特别是要运行无限长时间的程序时。
  • 24. 8.4.3 多线程服务器实例 【例8.1】下面进行客户机/服务器模式下的Socket 编程,包括一个服务器和一个客户机的程序例子。服务器端程序负责监听客户机请求,为每个客户机请求建立Socket 连接,从而为客户机提供服务。本程序提供的服务为:读取来自客户机的命令,根据客户机的命令,决定服务器要发给客户机的信息,并发送给客户机。
  • 25. 8.4.3 多线程服务器实例 (1) TCP/IP 服务器ServerSocket // ==================== Program Discription ======================== // 程序名称: SimpleServer.java // 程序目的:TCP/IP服务器应用程序依靠Java技术语言提供的网络类。ServerSocket类 // 完成建立一个服务器所需的大部分工作。在本机端口5432提供时间服务 //============================================================= import java.io.*; import java.util.*; import java.net.*; public class SimpleServer { public static void main(String args[]) {
  • 26. 8.4.3 多线程服务器实例 ServerSocket s = null; Socket s1; OutputStream s1out; DataOutputStream dos; //String line="only one line."; try { s = new ServerSocket(5432); // Register your service on port 5432 } catch (IOException e) {}// Run the listen/accept loop forever while (true) { try {
  • 27. 8.4.3 多线程服务器实例 s1 = s.accept();// Wait here and listen for a connection s1out = s1.getOutputStream(); // Get a communication stream for soocket dos = new DataOutputStream(s1out); dos.writeUTF(new Date().toString()); // Send string!(UTF provides machine-independent format) //dos.writeUTF(line); s1out.close(); // Close the connection, but not the server socket s1.close(); } catch (IOException e) {} } } }
  • 28. 8.4.3 多线程服务器实例 (2) 客户端Socket // ==================== Program Discription ========================= // 程序名称: SimpleClient.java // 程序目的:客户端Socket完成了建立一个连接所需的大部分工作。客户连接到服务器上,显 // 示服务器发送的所有时间数据。通过Socket获得服务器提供的时间字符串,并显示 //============================================================= import java.net.*; import java.io.*; public class SimpleClient { public static void main(String args[]) throws IOException { Socket s1; InputStream s1In; DataInputStream dis; String st;
  • 29. 8.4.3 多线程服务器实例 s1 = new Socket("127.0.0.1",5432); //Open your connection to sunbert, at port 5432 s1In = s1.getInputStream(); //Get an inputStream from the socket and read the input dis = new DataInputStream(s1In); st = new String (dis.readUTF()); System.out.println(st); // When done, just close the connection and exit s1In.close(); s1.close(); } } 运行结果如图8-4所示。
  • 30. 8.4.3 多线程服务器实例 图8-4 运行结果(例8.1)
  • 31. 8.5 数据报 8.5.1 DatagramPacket 8.5.2 DatagramSocket 8.5.3 数据报实例 8.5.4 组播套接字 MulticastSocket
  • 32. 8.5 数据报 TCP/IP是一种面向连接的协议,而用UDP 是一种无连接的协议,它只是把数据的目的地记录在数据报中,然后直接放在网络上,不保证传送质量。 在java.net包中有3个类支持基于UDP协议的网络通信: 表示数据报的DatagramSocket类; 用于端到端通信的DatagramPacket类; 用于广播通信的MulticastSocket类。
  • 33. 8.5.1 DatagramPacket 1. 将数据打包 java.net包中的DatagramPacket类用来创建数据报。数据报有两种,一种用来传递数据报,该数据报有要传递到的目的地址;另一种数据报用来接收传递过来的数据报中的数据。分别用DatagramPacket 的两个构造函数来创建。 (1) DatagramPacket(byte[] recvBuf, int readLength) 用来建立一个字节数组以接收UDP包。byte 数组在传递给构造函数时是空的,而int 值用来设置要读取的字节数(不能比数组的大小还大)。
  • 34. 8.5.1 DatagramPacket (2) DatagramPacket(byte[] sendBuf, int sendLength, InetAddress iaddr, int iport) 用来建立将要传输的UDP包。sendLength不应该比sendBuf字节数组的大小还大。如果数据报长度超出length,则触发IllegalArgument Exception。不过这时RuntimeException不需要用户代码捕获。 2. 使用数据报 通过接收数据报对象,获取数据报中的信息的方法有以下几个。 (1) public InetAddress getAddress() 如果是发送数据报,则获得数据报要发送的目标地址,但是如果是接收数据报,则返回发送此数据报的源地址。
  • 35. 8.5.1 DatagramPacket(2) public byte[]getData() 返回一个字节数组,其中是数据报的数据。如果想把字节数组转换成其他类型,就要进行转化。 (3) public int getLength() 获得数据报中数据的字节数。 (4) pubic int getPort() 返回数据报中的目标地址的主机端口号。通过发送数据报对象设置发送数据报中的信息的方法有:setAddress(InetAddress iaddr)、setPort(int iport)、setData(byte[] buf)、setData(byte[] buf, int offset, int length)、setLength(intlength)。详细资料可查Java文档。
  • 36. 8.5.2 DatagramSocket 发送和接收数据报还需要发送和接收数据报的Socket,即DatagramSocket 对象。DatagramSocket 用来读写UDP 包。它在本地机器端口监听是否有数据到达或者将数据报发送出去。DatagramSocket 类有3 个构造函数,允许指定要绑定的端口号和Internet 地址。 (1) public DatagramSocket() 用本地机上任何一个可用的端口创建一个套接字,这个端口号是由系统随机产生的。使用方法如下。 try { DatagramSocket datas=new DatagramSocket(); //发送数据报 } catch(SocketException e) { //异常处理 }
  • 37. 8.5.2 DatagramSocket这种构造方法没有指定端口号,可以用在客户端。如果构造不成功则触发SocketException 异常。 (2) public DatagramSocket(int port) 用一个指定的端口号port 创建一个套接字。当不能创建套接字时就抛出SocketException 异常,其原因是指定的端口已被占用或者是试图连接低于1024 的端口,但是又没有权限。 (3) DatagramSocket(int port, InetAddress iaddr) 绑定指定地址的指定端口。
  • 38. 8.5.3 数据报实例 【例8.2】基于UDP 的服务器/客户端通信程序。 (1) 创建UDP服务器 // ==================== Program Discription ======================= // 程序名称:UDPServer.java // 程序目的:UDP服务器在8000端口监听客户的请求。当它从客户接收到一个 // DatagramPacket时,它发送服务器上的当前时间 //================================================================= import java.io.*; import java.net.*; import java.util.*; public class UDPServer { //This method retrieves the current time on the server public byte[] getTime() {
  • 39. 8.5.3 数据报实例 Date d= new Date(); return d.toString().getBytes(); } // Main server loop. public void go() throws IOException { DatagramSocket datagramSocket; DatagramPacket inDataPacket; // Datagram packet from the client DatagramPacket outDataPacket; // Datagram packet to the client InetAddress clientAddress; // Client return address int clientPort; // Client return port byte[] msg= new byte[10]; // Incoming data buffer. Ignored. byte[] time; // Stores retrieved time // Allocate a socket to man port 8000 for requests. datagramSocket = new DatagramSocket(8000); System.out.println("!!!!!!at UDPServer,datagramSocket is: " + datagramSocket.getPort() + "local is: " + datagramSocket.getLocalPort()); System.out.println("UDP server active on port 8000"); // Loop forever while(true)
  • 40. 8.5.3 数据报实例 { // Set up receiver packet. Data will be ignored. inDataPacket = new DatagramPacket(msg, msg.length); // Get the message. datagramSocket.receive(inDataPacket); // Retrieve return address information, including InetAddress // and port from the datagram packet just recieved. clientAddress = inDataPacket.getAddress(); clientPort = inDataPacket.getPort(); // Get the current time. time = getTime(); //set up a datagram to be sent to the client using the //current time, the client address and port outDataPacket = new DatagramPacket (time, time.length, clientAddress, clientPort); //finally send the packet datagramSocket.send(outDataPacket); } }
  • 41. 8.5.3 数据报实例 public static void main(String args[]) { UDPServer udpServer = new UDPServer(); try { udpServer.go(); } catch (IOException e) { System.out.println("IOException occured with socket."); System.out.println(e); System.exit(1); } } } 运行结果如图8-5所示。
  • 42. 8.5.3 数据报实例 图8-5 运行结果(例8.2(1))
  • 43. 8.5.3 数据报实例(2) UDP 客户端 // ==================== Program Discription ======================= // 程序名称:UDPClient.java // 程序目的:UDP客户向前面创建的客户发送一个空包并接收一个包含服务器实际时间的包 // ================================================================ import java.io.*; import java.net.*; class UDPClient { public void go() throws IOException, UnknownHostException { DatagramSocket datagramSocket; DatagramPacket outDataPacket; // Datagram packet to the server DatagramPacket inDataPacket; // Datagram packet from the server InetAddress serverAddress; // Server host address byte[] msg = new byte[100]; // Buffer space.
  • 44. 8.5.3 数据报实例 String receivedMsg; // Received message in String form. // Allocate a socket by which messages are sent and received. datagramSocket = new DatagramSocket(); System.out.println("!!!!!!at UDPClient,datagramSocket is: " + datagramSocket.getPort() + "local port is: " +datagramSocket.getLocalPort()); // Server is running on this same machine for this example. // This method can throw an UnknownHostException. serverAddress = InetAddress.getLocalHost(); // Set up a datagram request to be sent to the server. // Send to port 8000. outDataPacket = new DatagramPacket(msg, 1, serverAddress, 8000); // Make the request to the server. datagramSocket.send(outDataPacket); // Set up a datagram packet to receive server's response. inDataPacket = new DatagramPacket(msg, msg.length); // Receive the time data from the server datagramSocket.receive(inDataPacket); // Print the data received from the server
  • 45. 8.5.3 数据报实例 receivedMsg = new String (inDataPacket.getData(), 0, inDataPacket.getLength()); System.out.println(receivedMsg); //close the socket datagramSocket.close(); } public static void main(String args[]) { UDPClient udpClient = new UDPClient(); try { udpClient.go(); } catch (Exception e) { System.out.println ("Exception occured with socket."); System.out.println (e); System.exit(1); } } } 运行结果如图8-6所示。
  • 46. 8.5.3 数据报实例 图8-6 运行结果(例8.2(2))
  • 47. 8.5.4 组播套接字 MulticastSocket DatagramSocket只允许数据报发往一个目的地址。java.net类包中提供了类MulticastSocket,允许将数据报以广播的方式发送到某个端口的所有客户。MulticastSocket 类是DatagramSocket类的子类。它在客户端(接收端)使用,监听服务器端广播来的数据;而服务器端仍然使用DatagramSocket来发送数据,只是发送的数据报的目的地址有所变化。其构造方法如下。 public MulticastSocket() public MulticastSocket(int port):在指定的端口通信。
  • 48. 8.5.4 组播套接字 MulticastSocket这两个方法都将抛出异常IOException,在程序中需要捕获处理。MulticastSocket类的主要方法如下。 public void joinGroup(InetAddress mcastaddr):加入一个广播组。 public void leaveGroup(InetAddress mcastaddr):离开一个广播组。 public void setTimeToLive(int ttl):指定数据报发送时间。 public void send(DatagramPacket p, byte ttl):在指定的时间内将数据报发送出去。
  • 49. 8.6 URL资源 8.6.1 InetAddress 类 8.6.2 URL和URLConnection
  • 50. 8.6 URL资源 连接到网络中的每台计算机(或其他设备)都有惟一的地址,这就是IP 地址。java.net.InetAddress 类是Java的IP地址封装类,它不需要用户了解如何实现对IP 地址操作的细节。 在互联网上,以URL(统一资源定位器)表示Internet上各种数据资源的地址。为了处理方便,Java将URL 封装成URL 类,可以用一个URL 对象记录下完整的URL 信息。
  • 51. 8.6.1 InetAddress 类 如果需要在主机名与Internet 地址之间进行转换,那么可以使用InetAddress 类。 InetAddress 类的定义如下: public final class InetAddress extends object implements Serializable{…} 该类中有两个字段:hostName(String)和address(int),即主机名和IP地址。这两个字段是不公开的,不能直接访问它们。 InetAddress类没有构造方法,要创建该类的实例对象,可以通过该类的静态方法获得该对象。找不到本地机器的地址时,这些方法通常会抛出UnknownHostException 异常,应在程序中捕获处理。
  • 52. 8.6.1 InetAddress 类 (1) public static InetAddress getLocalHost() getLocalHost 方法用于获得本地机的InetAddress对象,查找不到本地机的地址时,抛出一个UnknownHostException 异常。可以使用下面的格式进行异常捕获。 try { InetAddress address=InetAddress.getLocalHost(); …;//其他处理代码 } catch(UnknownException e){ …;//异常处理代码 }
  • 53. 8.6.1 InetAddress 类 (2) public static InetAddress getByName(String host) getByName(String host)方法用于获得由host 指定的InetAddress 对象。参数host 可以是一个机器名,也可以是一个IP地址或一个DSN 域名。 例如: InetAddress address=InetAddress.getByName("sun.java.com"); 将返回一个InetAddress 对象,封装了4 个字节的序列。可以使用getAddress()方法访问这些字节,如: Byte[] addresses=InetAddress.getAddress(); (3) public static InetAddress[] getAllByName(String host) 有些主机名可以带有许多对应于多个Internet 地址的信息,以利于实现负载平衡。如java.sun.com 对应3 个不同的地址,在主机被访问时随机选择一个地址。GetAllByName 用来获取所有的主机地址对象,并存放在一个地址对象数组中。
  • 54. 8.6.1 InetAddress 类(4) public static InetAddress getByAddress(Byte[] addr) 根据给定的IP 字节地址创建一个InetAddress对象。如果addr是IPv4地址,则返回一个Inet4Address 对象,如果是IPv6 地址,则返回一个Inet6Address 对象。IPv4 地址字节数组必须是4个字节,IPv6 地址字节数组必须是16 个字节。
  • 55. 8.6.1 InetAddress 类【例8.3】查询IP地址举例,程序如下。 import java.net.*; public class getIP { public static void main(String args[]) { InetAddress sun = null; try { sun = InetAddress.getByName("www.sun.com"); } catch(UnknownHostException e) {} System.out.println(sun); } } 运行结果如图8-7所示。
  • 56. 8.6.1 InetAddress 类 图8-7 运行结果(例8.3)
  • 57. 8.6.2 URL和URLConnection URL和URLConnection类封装了大量从远程站点检索信息的复杂细节,支持对HTTP和FTP资源的访问,例如可以使用如下语句构造URL对象: URL url=new URL("www.openlab.ca"); URL url=new URL("ftp://username:password@openlab.ca");
  • 58. 8.6.2 URL和URLConnection 1. URL 类的构造方法 在java.net包中提供了类URL来表示URL。类URL提供了很多构造方法来生成一个URL 对象: (1) public URL(String spec) (2) public URL(URL context, String spec) 后一个构造方法用已存在的URL 对象context 创建URL 对象。 (3) public URL(String protocol, String host, String file) 该构造方法用指定的协议、主机名、路径及文件名创建URL 对象。 (4) public URL(String protocol, String host, int port, String file) 该构造方法用指定的协议、主机名、端口号、文件路径及文件名创建一个URL对象。
  • 59. 8.6.2 URL和URLConnection 以下是一些具体的构造示例: URL url1 = new URL("http://www.edu.cn/HomePage/zhong_guo_jiao_yu/index.shtml"); URL base = new URL("http://www.edu.cn/HomePage"); URL url2 = new URL(base, "/jiao_yu_zi_yuan/index.shtml"); URL url3 = new URL("http", "www.edu.cn","/HomePage/jiao_yu_zi_yuan/index.shtml"); URL url4 = new URL("http", "www.abc.com", 8080, "/java/network.html");
  • 60. 8.6.2 URL和URLConnection 2. URL 类常用方法 一个URL 对象生成后,其属性是不能被改变的(与String 对象相似),但可以通过它给定的方法来获取这些属性。 (1) public final Object getContent():这个方法取得传输协议。 (2) public String getFile():这个方法取得资源的文件名。 (3) public String getHost():这个方法取得机器的名称。 (4) public int getPort():这个方法取得端口号。 (5) public String getProtocol():这个方法取得传输协议。
  • 61. 8.6.2 URL和URLConnection (6) public String toString():这个方法把URL 转化为字符串。 在Java中可以通过URL 读取WWW 信息。通过URL 类提供的openStream()方法,就可以读取URL 对象所指定的资源。 (7) public final InputStream openStream() 方法openStream()与指定的URL 建立连接并返回一个InputStream对象,将URL位置的资源转成一个输入数据流。通过这个InputStream对象,就可以读取资源中的数据。使用URL类获得服务器端的数据。
  • 62. 8.6.2 URL和URLConnection【例8.5】使用URL类举例,程序如下。 import java.net. *; import java.io.*; class Myurl { public static void main(String args[]) { try { URL url=new URL("http://java.sun.com:80/downloads/index.htm"); System.out.println("the Protocol: "+url.getProtocol()); System.out.println("the hostname: " +url.getHost() ); System.out.println("the port: "+ url.getPort()); System.out.println("the file:"+url.getFile()); System.out.println(url.toString()); } catch(MalformedURLException e) { System.out.println(e); } } }
  • 63. 8.6.2 URL和URLConnection运行结果如图8-9所示。 图8-9 运行结果(例8.5)
  • 64. 8.6.2 URL和URLConnection3. 创建URLConnection 对象 通过URL类的openStream()方法,只能从网络上读取资源中的数据。通过URLConnection类,可以在应用程序和URL 资源之间进行交互,既可以从URL 中读取数据,也可以向URL中发送数据。URLConnection 类表示了应用程序和URL 资源之间的通信连接。
  • 65. 8.6.2 URL和URLConnection4. URLConnection 类的常用方法 URLConnection 类不仅可以使用getInputStream()方法获得URL 节点的信息,还可以使用getOutputStream()方法向URL 节点传输数据,这样在本机与URL 节点间形成一个遵循HTTP协议的数据流通道。 URLConnection 类最常用的方法是: (1) public InputStream getInputStream() (2) public OutputStream getOutputStream()
  • 66. 8.6.2 URL和URLConnection【例8.6】使用URLConnetion类举例,程序如下。 import java.io.*; import java.net.*; import java.util.Date; class URLDemoTest { public static void main(String args[]) throws Exception { System.out.println("starting..."); int c; URL url=new URL("http://www.sun.com"); URLConnection urlcon=url.openConnection(); System.out.println("the date is :"+new Date(urlcon.getDate())); System.out.println("content_type :"+urlcon.getContentType()); InputStream in=urlcon.getInputStream(); while (((c=in.read())!=-1)) { System.out.print((char)c); } in.close(); } }
  • 67. 8.6.2 URL和URLConnection运行结果如图8-10所示。 图8-10 运行结果(例8.6)
  • 68. 8.7 网络聊天程序实例 本节利用Java来做一个网络聊天程序,来展示Java在网络上应用的强大功能。 聊天室是Internet上重要的交流场所,也是很多网民最热衷的交流方式。聊天室服务器负责对整个聊天室进行管理,包括用户登录认证、用户列表维护、信息转发等。本例将就聊天室的服务器和客户端编程进行分别讲解。
  • 69. 8.7 网络聊天程序实例 1. 服务器设计 当在控制台启动后,就可使用客户端进行登录,实例的运行效果如下所示,在控制台显示用户连接和断开的信息: Server start... /192.168.2.49连接 k001/192.168.2.49断开连接 /192.168.2.49连接 (1) 启动服务器 ServerSocket与Socket类的用法可参考TCP服务器与TCP客户端例子。Client类用于与客户端作信息交流,每连接上一个客户,就生成一个线程用于与该客户端的通信。
  • 70. 8.7 网络聊天程序实例 (2) 更新在线用户信息 更新过程为遍历整个clients向量,取得客户端的名字,并发送给每个客户端。 Vector类的size方法可返回该向量的大小,elementAt方法可返回在特定位置的元素,注意这里返回的元素为Object对象,需要显式转换为Client对象。最后调用自定义的sendClients方法发送信息到客户端。
  • 71. 8.7 网络聊天程序实例 (3) Client类的实现 本例中聊天室的服务器用多线程实现,每当一个新的用户连接到服务器时,就实例化一个新的线程来与该客户端通信。 Client类负责维护客户端的相关信息,比如IP地址、聊天室中的用户名、连接端口等,并实现了信息发送的send方法。
  • 72. 8.7 网络聊天程序实例 2. 客户端设计 以Applet的方式实现了一个聊天室的客户端,可通过本例来实现聊天功能,实例的运行效果如图8-11所示。 (1) 用户界面 采用BorderLayout的布局管理器,分为上中下三层,各为一个面板(JPanel)。上方放置一个输入用户名的文本输入域,一个“连接”按钮和一个“断开连接”按钮;中间为一个显示信息的文本框和一个显示当前在线用户的列表框;下方为输入聊天信息的文本输入域和一个“发送”按钮。
  • 73. 8.7 网络聊天程序实例 图8-11 运行结果
  • 74. 8.7 网络聊天程序实例(2) 事件处理 在Applet中,事件处理可通过覆盖action方法来实现。 public boolean action(Event evt,Object obj) {} Event类的target属性可判断事件的来源,与相应的组件做比较,就可确定用户的操作行为。本例以发送信息为例,在if语句中确认事件来源为“发送”按钮,构造一个字符串,以“MSG:”关键字开始,加上从信息输入文本域输入的文本,然后用PrintStream类的println方法将字符串输出。
  • 75. 8.7 网络聊天程序实例(3) 监听线程的实现 Listen类用于与服务器进行通信,并维护一些连接信息。在构造函数里面,用Socket类的getInputStream和getOutputStream方法获取与服务器通信的输入流和输出流。
  • 76. 8.8 课后练习 1. 填空题 (1) Java 的许多网络类都包含在________包中。 (2) _________类的对象包含一个IP地址。 2. 选择题 (1) 下面不属于TCP/IP参考模型的是( )。 A. 应用层 B. 运输层 C. 网际层 D. 会话层 (2) 下面不是通用的服务的是( )。 A. FTP B. HTTP C. TELNET D. WWW 3. 判断题 (1) 已建立的URL对象不能被改变。 ( ) (2) UDP是面向连接的协议。 ( )
  • 77. 8.8 课后练习 4. 简答题 (1) UDP与TCP协议有什么不同? (2) 什么是URL连接? (3) TCP网络编程中主要用到哪两个类? 5. 操作题 (1) 使用TCP Socket/ServerSocket对象编写两个类TCPClient和TCPServer。TCPClient将连接到TCPServer上并发送多行文字。TCPServer收到这些文字,并输出到屏幕上。 (2) 编写两个类ChatClient和ChatServer。ChatServer将修改上题中的TCPServer类,使用多线程机制,能同时对多个客户端发来的文字做出响应。
  • 78. Q & A? Thanks!