1、1,Java面向对象程序设计,第10章 Java网络编程,2,本章主要内容,了解常见的网络协议 理解端口和套接字 掌握InetAddress类 掌握ServerSocket类 学习编写TCP、UDP程序,3,网络编程概述,网络编程是指编写程序完成两台或多台计算机之间信息的通信。 计算机之间如果要通过网络通信,必须遵守一定的规矩,这个规矩就是各种网络协议。 最有名的协议就是TCP/IP协议。TCP协议解决了信息可靠传输的问题,而IP协议解决了网络计算机定位的问题。 一台主机都需要有一个唯一的标记,即IP地址。例如:192.168.0.1。 DNS(域名服务器)实现了域名与IP地址之间的映射。例如
2、:的IP地址是119.75.213.36。,4,使用InetAddress类实现网络定位,演示使用InetAddress类,5,使用URL类访问网络资源,构造方法: URL(String host) URL baidu = new URL(“http:/”); URL(URL url, String relative) URL url = new URL(baidu, “s?wd=java”) 。 URL(String protocol, String host, int port, String file) URL url = new URL(“http”, “”, 80, “”)。 通过U
3、RL访问网络资源的方法需要3步: 1. 创建URL对象。 2. 使用URL对象的openStream( )方法获取一个InputStream对象。 3. 从此InputStream读入即可。,try URL bd = new URL(“http:/ r = new BufferedReader(new InputStreamReader(bd.openStream();String line = null;while (null != (line = r.readLine() System.out.println(line);r.close(); catch (MalformedURLExce
4、ption e) e.printStackTrace(); catch (IOException e) e.printStackTrace(); ,6,Socket,套接字(Socket ):计算机之间相互通讯的一种方式,表示一个系统的IP地址和端口号的结合。 Socket编程包括TCP网络编程和UDP网络编程。 利用Socket编写通信程序时,需要区分服务器端编程和客户端编程,两者的功能和编写方法不一样。对于服务器端编程来说,服务器端需要有一个监听进程,该进程绑定一个端口负责监听客户端的连接请求。客户端创建一个Socket,并请求与服务器建立连接。服务器在接收到连接请求后,建立一个新的Soc
5、ket并绑定一个新的端口与客户建立连接。服务器继续在原端口监听,等待新的请求。,7,TCP与UDP,TCP协议是一种面向连接的协议,该协议在两台计算机之间建立一条可靠的逻辑连接线路,能够自动处理网络上经常发生的各种错误。 UDP协议是面向无连接的协议。该协议将需要传输的信息分拆成一个个独立的数据包,为每一个数据包填写上目的地址,然后将它们送到网络上。UDP协议是一个不可靠的协议,数据包可能会发生丢失、错误、乱序等情况,但它的效率非常高。 端口并不是一个物理上的概念,而是一个逻辑上的连接装置,任何一个网络连接必须要使用一个端口。端口可以是一个065535之间的整数,1024以下的数字是保留的每一
6、台主机只有一条到网络的物理连接,当访问一台提供了多种服务的服务器时,客户端只需要使用不同的端口就可以确定连接到服务器的哪项服务上。,8,TCP网络编程,创建TCP Socket需要的四个信息: 本地系统的IP 本地应用程序使用的TCP端口号 远程系统的IP 远程应用程序相应的TCP端口号 ServerSocket和Socket两个类用于建立一个双边的通信。 服务器端:创建ServerSocket类的对象用于侦听客户端的Socket连接,如果没有连接,它将一直等待。 客户端:创建Socket类的对象连接到一个服务器端。,9,Socket TCP通信模型,图10.2是客户端与服务器端通信的工作流程
7、。,Server端,/占用服务器某个端口监听 ServerSocket ss =new ServerSocket (PORT);,/等待连接 Socket s = ss.accept();,/输入流 s.getInputStream();,/输出流 s.getOutputStream();,/关闭socket s.close(); ss.close();,Client端,/试图连接 Socket s =new Socket(IP, PORT);,/输入流 s.getInputStream();,/输出流 s.getOutputStream();,/关闭socket s.close();,10,
8、服务器端与客户端简单通信实例,/服务器端 ServerSocket ss = null; BufferedReader in = null; BufferedWriter out = null; try ss = new ServerSocket(8888);System.out.println(“开始监听,端口号:8888.“);Socket s = null;try s = ss.accept();in = new BufferedReader(new InputStreamReader(s.getInputStream();out = new BufferedWriter(new Out
9、putStreamWriter(s.getOutputStream();String str = in.readLine(); /读取客户端的数据System.out.println(“服务器接收到数据:“ + str); finally s.close(); catch (IOException e) e.printStackTrace(); finally try ss.close(); catch (IOException e) e.printStackTrace(); ,11,服务器端与客户端简单通信实例,/客户端 Socket s = null; BufferedReader in
10、= null; BufferedWriter out = null; try s = new Socket(“127.0.0.1“, 8888);in = new BufferedReader(new InputStreamReader(s.getInputStream();out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream();Scanner input = new Scanner(System.in);out.write(input.nextLine(); /向服务器端发送数据out.flush(); catc
11、h (UnknownHostException e) e.printStackTrace(); catch (IOException e) e.printStackTrace(); finally try s.close(); catch (IOException e) e.printStackTrace(); ,12,服务器同时为多个客户端服务,对Server类做了修订,在建立连接之后,不再是直接与客户端交互,而是把得到的Socket交给一个ServerThread线程,由ServerThread线程负责和客户端交互。 为了模拟多客户端连接的效果,对Client类做了修改,与服务器建立连接后
12、也不再直接与服务器交互,而是交给一个线程来负责,并且同时运行多个线程。,13,服务器端,/服务器端 public class MultiServer 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 ServerThre
13、ad(socket); catch (IOException e) socket.close( ); finally s.close( ); ,/服务器端线程 class ServerThread extends Thread private Socket socket;private BufferedReader in;private PrintWriter out;public ServerThread(Socket s) throws IOException socket = s;in = new BufferedReader(new InputStreamReader(socket.g
14、etInputStream( );out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream( ), true);start( ); public void run( ) ,14,客户端,/客户端 public class MultiClient static final int MAX_THREADS = 40;public static void main(String args) throws IOException,InterruptedException while (t
15、rue) if (ClientThread.threadCount( ) MAX_THREADS)new ClientThread(“127.0.0.1”, 8888);Thread.currentThread( ).sleep(100); ,/客户端线程 class ClientThread extends Thread private Socket socket;private BufferedReader in;private PrintWriter out;public ClientThread(String ip, int port) threadcount+;try socket
16、= new Socket(ip, port);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( ) ,15,UDP网络编程,接收端:
17、 调用DatagramSocket(int port)创建一个套接字socket,并绑定到指定端口上;调用DatagramPacket构造方法创建一个缓冲区来接收UDP包 ;调用DatagramSocket类的receive方法,接收UDP包,如果此时还没有数据可供接收,receive方法将阻塞,直至接收到数据为止。关闭套接字socket。 发送端: 调用DatagramSocket()创建一个套接字socket;调用DatagramPacket构造方法创建要发送的UDP数据包,构造数据包时,需要提供要发送的数据、对方的地址、对方的端口号等信息;调用DatagramSocket类的send方法,发送UDP数据包;关闭套接字socket。,16,总结,使用InetAddress类实现网络定位 使用URL类访问网络资源 使用Socket套接字进行TCP、UDP网络通信 结合多线程实现网络编程,