70
1 Chapter 11 Java 网网网网 授授授授 授授授 授授授授授授 授授授授 Email:[email protected]

Chapter 11 : Java 网络编程

  • Upload
    venice

  • View
    124

  • Download
    0

Embed Size (px)

DESCRIPTION

Chapter 11 : Java 网络编程. 授课教师:赵小敏 浙江工业大学 软件学院 Email:[email protected]. 主要内容. 1 、 网络基础知识 2 、 Socket 和 ServerSocket 类 3 、基于 TCP 的 Java 编程 4 、基于 UDP 的 Java 编程 5 、基于 URL 类的 Java 网络编程. 1 、 网络基础知识. 计算机网络形式多样,内容繁杂。网络上的计算机要互相通信,必须遵循一定的协议。目前使用最广泛的网络协议是 Internet 上所使用的 TCP/IP 协议 - PowerPoint PPT Presentation

Citation preview

Page 1: Chapter 11 : Java 网络编程

1

Chapter 11 : Java 网络编程

授课教师:赵小敏浙江工业大学 软件学院Email:[email protected]

Page 2: Chapter 11 : Java 网络编程

2

主要内容

1 、 网络基础知识 2 、 Socket 和 ServerSocket 类 3 、基于 TCP 的 Java 编程 4 、基于 UDP 的 Java 编程 5 、基于 URL 类的 Java 网络编程

Page 3: Chapter 11 : Java 网络编程

3

1 、 网络基础知识

计算机网络形式多样,内容繁杂。网络上的计算机要互相通信,必须遵循一定的协议。目前使用最广泛的网络协议是 Internet 上所使用的 TCP/IP 协议

网络编程是指利用不同层次的通信协议提供的接口实现网络进程通信的编程。

网络编程中有两个主要的问题,一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输。在 TCP/IP 协议中 IP 层主要负责网络主机的定位,数据传输的路由,由 IP 地址可以唯一地确定 Internet 上的一台主机。而 TCP 层则提供面向应用的可靠的或非可靠的数据传输机制,这是网络编程的主要对象,一般不需要关心 IP 层是如何处理数据的。

Page 4: Chapter 11 : Java 网络编程

4

1 、网络基础知识 ( 续 2)

目前较为流行的网络编程模型是客户机 / 服务器( C/S )结构。即通信双方一方作为服务器等待客户提出请求并予以响应。客户则在需要服务时向服务器提出申请。服务器一般作为守护进程始终运行,监听网络端口,一旦有客户请求,就会启动一个服务进程来响应该客户,同时自己继续监听服务端口,使后来的客户也能及时得到服务。

Page 5: Chapter 11 : Java 网络编程

5

1 、网络基础知识 ( 续 3)

网络进程是指在网络结点计算机上运行的程序 通信协议指网络进程之间的通信必须遵循预定

的规则。 TCP/IP 是一组在 Internet 网络上的不同计算

机之间进行通信的协议的总称,它由应用层的HTTP 、 FTP 、 SMTP 和传输层的 TCP 及网络层的 IP 等一系列协议组成。

Page 6: Chapter 11 : Java 网络编程

6

TCP/UDP/IP

TCP (传输控制协议)是面向连接的、可靠的点对点的传输协议。

UDP (用户数据报协议)是无连接的不可可靠的传输协议。

IP 是网络层协议,实现按 IP 地址的网络路由的功能。

Page 7: Chapter 11 : Java 网络编程

7

TCP

通过 TCP 协议传输,得到的是一个顺序的无差错的数据流。发送方和接收方的成对的两个socket 之间必须建立连接,以便在 TCP 协议的基础上进行通信,当一个 socket (通常都是 server socket )等待建立连接时,另一个socket 可以要求进行连接,一旦这两个socket 连接起来,它们就可以进行双向数据传输,双方都可以进行发送或接收操作。

Page 8: Chapter 11 : Java 网络编程

8

UDP

UDP 是 User Datagram Protocol 的简称,是一种无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。

Page 9: Chapter 11 : Java 网络编程

9

套接字

“ 套接字”或者“插座”( Socket )也是一种软件形式的抽象,用于表达两台机器间一个连接的“终端”。

针对一个特定的连接,每台机器上都有一个“套接字”,可以想象它们之间有一条虚拟的“线缆”。线缆的每一端都插入一个“套接字”或者“插座”里。

进程之间要实现通信首先要建立各自的套接字。 在 Java 中,我们创建一个套接字,用它建立与其他

机器的连接。

Page 10: Chapter 11 : Java 网络编程

10

TCP/IP 中的端口号 机器内独一无二的场所

有些时候,一个 IP 地址并不足以完整标识一个服务器。这是由于在一台物理性的机器中,往往运行着多个服务器(程序)。由 IP表达的每台机器也包含了“端口”( Port )。

TCP/IP 系统中的端口号是 16 位的数字,从 0 ~65535 。一般<=1023 由预先定义的服务占用,如 telnet,SMTP mail 、 ftp 等。

Client 与 Server 在建立连接前,必须事先约定号端口号。

Page 11: Chapter 11 : Java 网络编程

11

Java 网络程序设计支持机制

•利用 URL访问网络资源•利用 Socket通信

支持 Socket通信的类

网 络

Java网络应用系统

支持 URL的类

Page 12: Chapter 11 : Java 网络编程

12

Java 网络程序设计支持机制

支持网络通信的类在 java.net 包中。 URL, URLConnection, Socket, ServerSocket ,使

用 TCP 实现网络通信。 DatagramPacket, DatagramSocket,

MulticastSocket 支持 UDP 通信方式。

Page 13: Chapter 11 : Java 网络编程

13

2 、 Socket 和 ServerSocket 类

客户套接字类( Socket ) 服务器套接字类( ServerSocket )

Page 14: Chapter 11 : Java 网络编程

14

套接字类 Socket

1 、 Socket 的四种构造方法(1) Socket ( String host , int port ) thows

UnknownHostException , IOException 创建一个面向连接的套接字对象,并将其连接至特定的主

机( host )的特定端口( port )(2) Socket ( String host , int port , boolean strea

m ) 创建一个套接字对象,并将其连接至特定的主机的特定端

口上,此套接字对象是面向连接的还是数据报的,则由最后的一个参数决定

Page 15: Chapter 11 : Java 网络编程

15

套接字类 Socket

1 、 Socket 的四种构造方法(3) Socket ( InetAddress address , int port ) 创建一个面向连接的套接字对象,并将其连接至特定 IP

的主机的特定端口( port )(4) Socket ( InetAddress address , int

port , boolean stream ) 创建一个套接字对象,并将其连接至特定 ip 主机的特定

端口上,此套接字对象是面向连接的还是数据报的,则由最后的一个参数决定

Page 16: Chapter 11 : Java 网络编程

16

套接字类 Socket

2 、 Socket 提供的主要方法(1) InetAddress getInetAddress () 返回该套接字所连接的 IP 地址(2) Int getPort()

返回该套接字所连接的远程端口(3) sychronized void close() throws IOException

关闭套接字

Page 17: Chapter 11 : Java 网络编程

17

套接字类 Socket

2 、 Socket 提供的主要方法(4) InputStream getInputStream () throws IOException

获得套接字绑定的数据的输入流(5) PrintStream getOutputStream() throws IOException

获得向套接字绑定的数据输出流

Page 18: Chapter 11 : Java 网络编程

18

服务器套接字 (ServerSocket)

1 、 ServerSocket 类的构造方法(1) ServerSocket(int port) throws IOException

构造一个 ServerSocket 对象,其绑定的端口号为port

(2) ServerSocket(int port , int count)

构造一个 ServerSocket 对象,其绑定的端口号为 port,如 port 为 0 ,则该对象与缺省的端口号绑定。其中count 为该对象端口上等待的连接的客户最大数

Page 19: Chapter 11 : Java 网络编程

19

服务器套接字 (ServerSocket)

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

(2) Void close() throws IOException 关闭套接字

Page 20: Chapter 11 : Java 网络编程

20

怎样用 socket 进行客户与服务器通信

Socket 是两个实体之间进行通信的有效端点。通过socket 可以获得源 IP 地址和源端口、终点 IP 地址和终点端口。用户可以将多个 socket 连入同一个端口,以便对于单个端口可以有多个连接。

通过 socket 客户 / 服务器编程可以创建一个能被许多人使用的分布式程序,并且所有客户均可以用统一的前端进行工作,并与服务器进行通信。

Page 21: Chapter 11 : Java 网络编程

21

与服务器通信必须具备三个条件

服务器程序 客户程序 连接它们的 socket 程序

Page 22: Chapter 11 : Java 网络编程

22

ServerSocket 类

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

Page 23: Chapter 11 : Java 网络编程

23

Socket 类

getInputStream() 和 getOutStream() 方法来发送和捕捉数据。

try{

// 传递给它一个整数作为服务器指定可以使用的给定端口    ServerSocket myServerSocket=new ServerSocket(100);

   Socket my100Socket=myServerSocket.accept(); // 检测端口的活动    }catch(Exception e){}

Page 24: Chapter 11 : Java 网络编程

24

Accept() 方法直到接收到用户的连接请求,才继续执行中断的执行程序。一旦客户的连接成功, my100Socket 就代表该连接,并且可以发送和接收数据。

最后,我们看一看客户是怎样请求连接的。其连接方法如下:

try{

Socket mySocket=new Socket("www.cpcw.com",100);

}catch(Exception e ){}

Socket 类

Page 25: Chapter 11 : Java 网络编程

25

3 、基于 TCP 的 Java 网络编程

一对一的 Socket C/S 通信 TCP 是面向连接的、可靠的网络传输协议,当

两个网络进程准备进行通信时,都必须首先建立各自的一个套接字,其中服务器建立套接字后,侦听来自网络的客户连接请求,客户通过套接字,指定服务器的 IP 地址和端口号,便可与服务器进行通信。

Page 26: Chapter 11 : Java 网络编程

26

基于 TCP 的 C/S 连接方式

Page 27: Chapter 11 : Java 网络编程

27

( 一 )TCP 协议通信的服务器方实现

(1) 假设服务器工作在端口 8000 上,ServerSocket svrsoc= ServerSocket(8000)Socket soc = svrsoc.accept();// 监视端口 8000 的连接

请求(2) 打开与 soc 绑定的输入 / 输出流:In=new BufferedReader(new

InputStreamRead(soc.getInputStream()));// 在套接字 soc 上绑定的输入流基础上构造

BufferedReader 对象

Page 28: Chapter 11 : Java 网络编程

28

( 一 ) TCP 协议通信的服务器方实现(续)

out=new PrintWrite(new bufferedWrite(new OutputStreamWrite(soc.getOutputStream())),true);

// 在套接字 soc 上绑定的输出流基础上构造PrintWrite 对象

服务器使用 in 和 out 两个实例从客户接收输入信息和向客户程序发信息,同样,在客户端也应该建立这两个对象,用来与服务器程序进行双向通信。

Page 29: Chapter 11 : Java 网络编程

29

Page 30: Chapter 11 : Java 网络编程

30

( 一 ) TCP 协议通信的服务器方实现(续)

(3) 获取客户机的 IP 地址,并在服务器窗口中显示客户机的地址信息:

clientIP=soc.getInetAddress();

System.out.println(“Client’s IP address:”+clientIP);

Page 31: Chapter 11 : Java 网络编程

31

( 一 ) TCP 协议通信的服务器方实现(续)

(4) 读入一行客户的输入,并回显该行 String str = in.readLine();

while(!str.equals(“quit”));{

System.out.println(“Client said:”+str);

str=in.readLine();

}

Page 32: Chapter 11 : Java 网络编程

32

( 一 ) TCP 协议通信的服务器方实现(续)

(5) 不断循环以上代码,直到客户输入“ quit” 为止。

System.out.println(“Client want to leave.”);finall{ in.close(); out.close(); soc.close(); svrsoc.close();}

Page 33: Chapter 11 : Java 网络编程

33

( 二 ) 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);

Page 34: Chapter 11 : Java 网络编程

34

( 二 ) TCP 协议通信的客户方实现( 续 )

(3) 建立输入 / 输出流后,从服务器读取发来的” welcome!” 信息,显示在窗口:

Strin=in.readLine();

System.out.println(“Server said:”+strin);

Page 35: Chapter 11 : Java 网络编程

35

( 二 ) TCP 协议通信的客户方实现( 续 )

(4) 客户向服务器发送的数据流从键盘获取byte bmsg[]=new byte[200];

System.in.read(bmsg); //从键盘读入 bmsg

String msg=new String(bmsg,0); //byte 型转 String 型Msg=msg.trim(); //删除msg 两边的空格

Page 36: Chapter 11 : Java 网络编程

36

( 二 ) TCP 协议通信的客户方实现( 续 )

(5) 当键盘输入不是“ quit” 时,将键盘输入的数据写入输出流中,并发送出去,然后继续从键盘获取输入数据,不断循环,直到输入“ quit” 时,先将其传送给服务器,然后关闭输入 / 输出流和 Socket:

out.println(strout);In.close();out.close();soc.close();System.exit(0);

Page 37: Chapter 11 : Java 网络编程

一个简单的客户端 / 服务器程序1. import java.net.*; 2. import java.io.*; 3. import java.lang.*;

4. public class myserver{ 5. public static void main(String args[]){ 6. ServerSocket server; 7. Socket socket; 8. String s; 9. InputStream Is; 10. OutputStream Os; 11. DataInputStream DIS; 12. PrintStream PS;

13. try{ 14. server=new ServerSocket(4321); 15. socket=server.accept();16. System.out.println("server ok"); 17. System.out.println("************************************************"); 18. System.out.println("");

Page 38: Chapter 11 : Java 网络编程

19. Is=socket.getInputStream(); 20. Os=socket.getOutputStream(); 21. DIS=new DataInputStream(Is); 22. PS=new PrintStream(Os); 23. DataInputStream in=new DataInputStream(System.in); 24. while(true){ 25. System.out.println(""); 26. System.out.println("please wait client's message..."); 27. System.out.println(""); 28. s=DIS.readLine(); 29. System.out.println("client said:"+s); 30. if(s.trim().equals("BYE"))break; 31. System.out.print("you say:"); 32. s=in.readLine(); 33. PS.println(s); 34. if(s.trim().equals("BYE"))break; 35. } 36. DIS.close(); 37. PS.close(); 38. Is.close(); 39. Os.close(); 40. socket.close(); 41. } catch(Exception e){ 42. System.out.println("Error:"+e); 43. } //catch44. } //main45. } //public class

Page 39: Chapter 11 : Java 网络编程

1. import java.net.*; 2. import java.io.*; 3. import java.lang.*;

4. public class myclient{ 5. public static void main(String args[]){ 6. if (args.length<1){7. System.out.println("Please input the Server Name or IP!"); 8. System.out.println("see also: myclient 127.0.0.1"); 9. System.exit(1); } //if

10. Socket socket; 11. String s=“[email protected]"; 12. String len; 13. InputStream Is; 14. OutputStream Os; 15. DataInputStream DIS; 16. PrintStream PS; 17. try{ 18. socket=new Socket(args[0],4321);

19. System.out.println("client ok"); 20. System.out.println("************************************************"); 21. System.out.println("");

Page 40: Chapter 11 : Java 网络编程

22. Is=socket.getInputStream(); 23. Os=socket.getOutputStream(); 24. DIS=new DataInputStream(Is); 25. PS=new PrintStream(Os); 26. DataInputStream in=new DataInputStream(System.in); 27. while(true){ 28. System.out.print("you say:"); 29. s=in.readLine(); 30. PS.println(s); 31. if(s.trim().equals("BYE"))break; //32. else 33. { 34. System.out.println(""); 35. System.out.println("please wait server's message..."); 36. System.out.println(""); 37. } 38. s=DIS.readLine(); //´39. System.out.println("server said:"+s); 40. if(s.trim().equals("BYE"))break; } 41. DIS.close(); //42. PS.close(); //43. Is.close(); //44. Os.close(); // 45. socket.close(); //46. } catch(Exception e){ 47. System.out.println("Error:"+e); 48. } 49. } 50. }

Page 41: Chapter 11 : Java 网络编程

41

( 三 ) 支持多客户的 client/server 程序设计

在实际应用中,往往是在服务器上运行一个永久的程序,它可以接收来自其他多个客户端的请求,提供相应的服务。为了实现在服务器方给多个客户提供服务的功能,需要对上面的程序进行改造,利用多线程实现多客户机制。服务器总是在指定的端口上监听是否有客户请求,一旦监听到客户请求,服务器就会启动一个专门的服务线程来响应该客户的请求,而服务器本身在启动完线程之后马上又进入监听状态,等待下一个客户的到来。

Page 42: Chapter 11 : Java 网络编程

import java.io.*;import java.net.*;public class TalkClient {

public static void main(String args[]) {   try{    Socket socket=new Socket(“127.0.0.1”,4700);     // 向本机的 4700 端口发出客户请求

      BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));    // 由系统标准输入设备构造 BufferedReader 对象    PrintWriter os=new PrintWriter(socket.getOutputStream());    // 由 Socket 对象得到输出流,并构造 PrintWriter 对象

BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));

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

}

Page 43: Chapter 11 : Java 网络编程

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;      BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));   // 由 Socket 对象得到输入流,并构造相应的 BufferedReader 对象     PrintWriter os=newPrintWriter(socket.getOutputStream());       // 由 Socket 对象得到输出流,并构造 PrintWriter 对象     BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));       // 由系统标准输入设备构造 BufferedReader 对象    System.out.println("Client-"+ clientnum +":" +is.readLine());

Page 44: Chapter 11 : Java 网络编程

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

Page 45: Chapter 11 : Java 网络编程

import java.io.*;import java.net.*;import ServerThread;public class MultiTalkServer{

  static int clientnum=0; //静态成员变量,记录当前客户的个数  public static void main(String args[]) throws IOException {     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); //退出     }     while(listening){ // 永远循环监听     new ServerThread(serverSocket.accept(),clientnum).start();       // 监听到客户请求,根据得到的 Socket 对象和       客户计数创建服务线程,并启动之 System.out.println("Client-"+(clientnum+1)+" is connected...");

      clientnum++; //增加客户计数     }     serverSocket.close(); // 关闭 ServerSocket   }}

Page 46: Chapter 11 : Java 网络编程

46

4 、基于 UDP 协议的 Java 网络编程

利用 TCP 协议通信必须首先使客户和服务器之间建立一个专门的通道进行数据交换——效率低

UDP 协议把要发送的数据及对方的 IP 地址和端口号构成报文( datagram ),不与对方连接就把报文一个个独立地发送出去。

Page 47: Chapter 11 : Java 网络编程

47

Datagram

TCP/IP 传输层由两个并列的协议 :TCP,UDP. 一般套接字 (TCP) 提供一个可靠的传输模型作为两个

网络端点的字节流 , 有纠错能力 . UDP没有保持的连接和数据流 , 数据报是一个网络上

发送的独立信息 , 它的到达 , 到达时间 , 以及内容不能得到保证 . socket

server client

datagram

server client

Page 48: Chapter 11 : Java 网络编程

48

Datagram

TCP 提供高可靠性服务 ,适用于一次要传输交换大量报文的情况 , 信道上传递的包不需要源地址和目的地址

UDP 提供高效率服务 ,适用于依次传输交换少量报文的情形 ( 如数据库查询 ), 每个数据包要包含目的地址和端口号 .

数据报文的使用以包为中心 :打包 ,拆包 . Java.net 包支持两种不同的在网络上送数据的方

法 : 一般套接字和数据报文套接字 .

Page 49: Chapter 11 : Java 网络编程

49

Datagram

发出报文的标准步骤如下 :1. 定义数据成员 DatagramSocket socket; DatagramPacket packet; InetAddress address;( 用来存放接收方的地址 ) int port; ;( 用来存放接收方的端口号 )2. 创建数据报文 Socket 对象 try {socket=new DatagramSocket(1111);} catch(java.net.SocketException e) {} socket 绑定到一个本地的可用端口 , 等待接收客户的请求 .

Page 50: Chapter 11 : Java 网络编程

50

Datagram

3.分配并填写数据缓冲区 ( 一个字节类型的数组 )

byte[] Buf=new byte[256];

存放从客户端接收的请求信息 .

4. 创建一个 DatagramPacket

packet=new DatagramPacket(buf, 256);

用来从 socket 接收数据 , 它只有两个参数 5. 服务器阻塞 socket.receive(packet);

在客户的请求报道来之前一直等待

Page 51: Chapter 11 : Java 网络编程

51

Datagram

6. 从到来的包中得到地址和端口号 InetAddress address=packet.getAddress();

int port=packet.getPort();

7. 将数据送入缓冲区 或来自文件 , 或键盘输入8. 建立报文包 , 用来从 socket 上发送信息 packet=new DatagramPacket

(buf,buf.length, address,port);

9. 发送数据包 10. 关闭 socket

socket.send(packet); socket.close();

Page 52: Chapter 11 : Java 网络编程

52

Datagram

客户端接收包的步骤如下 :

1. 定义数据成员 int port; InetAddress address;

DatagramSocket socket;

DatagramPacket packet;

byte[] sendBuf=new byte[256];

2. 建立 socket

socket=new DatagramSocket();

Page 53: Chapter 11 : Java 网络编程

53

Datagram

3. 向服务器发出请求报文 address=InetAddress.getByName(args[0]); port=parseInt(args[1]); packet=new DatagramPacket(sendBuf,256,address,port); socket.send(packet);

这个包本身带有客户端的信息4. 客户机等待应答 packet=new DatagramPacket(sendBuf,256);

socket.receive(packet);( 如果没有到就一直等待 , 因此实用程序要设置时间限度 )

Page 54: Chapter 11 : Java 网络编程

54

Datagram

5. 处理接收到的数据 String received=new String(packet.getData(),0);

System.out.println(received);

数据报套接字首先是强调发送方和接收方的区别 , 同时也指出服务器和客户之间的不同 :一个客户机必须事先知道服务器的地址和端口 , 以便进行出事连接一个服务器从它接收到的数据报文中读取客户端的地址和端口 .

Page 55: Chapter 11 : Java 网络编程

Datagram建立数据报 socket();

建立一个报文包 packet

等待请求报文

建立数据报 socket

建立一个请求包

发出请求

获得对方地址

构成信息包

发送出去

创建接收包

等待接收

Page 56: Chapter 11 : Java 网络编程

56

一个 UDP 协议的 C/S例子

UDPServer.java UDPClient.java

Page 57: Chapter 11 : Java 网络编程

57

5 、基于 URL 类的 Java 网络编程

统一资源定位器 URL

URL(Uniform Resource Locator) 是一致资源定位器的简称,它表示 Internet 上某一资源的地址。通过 URL我们可以访问 Internet 上的各种网络资源,比如最常见的 WWW , FTP站点。浏览器通过解析给定的 URL 可以在网络上查找相应的文件或其他资源。

Page 58: Chapter 11 : Java 网络编程

58

URL 的组成

protocol://resourceName  协议名( protocol )指明获取资源所使用的传输协议,如 http 、 ftp 、 gopher 、 file 等,资源名( resourceName )则应该是资源的完整地址,包括主机名、端口号、文件名或文件内部的一个引用。例如:http://www.sun.com/ 协议名 :// 主机 http://home.netscape.com/home/welcome.html 协议名 :// 机器名+文件名  http://www.gamelan.com:80/Gamelan/network.html#BOTTOM 协议名 :// 机器名+端口号+文件名+内部引用

Page 59: Chapter 11 : Java 网络编程

59

创建一个 URL

为了表示 URL , java.net 中实现了类 URL 。可以通过下面的构造方法来初始化一个 URL 对象:( 1 ) public URL (String spec);   通过一个表示 URL 地址的字符串可以构造一个URL 对象。    URL urlBase=new URL(“http://www. 263.net/”) ( 2 ) public URL(URL context, String spec);   通过基 URL 和相对 URL 构造一个 URL 对象。   URL net263=new URL (“http://www.263.net/”);   URL index263=new URL(net263, "index.html")

Page 60: Chapter 11 : Java 网络编程

60

创建一个 URL ( 续 )

( 3 ) public URL(String protocol, String host, String file);   new URL("http", "www.gamelan.com", "/pages/Gamelan.net. html");( 4 ) public URL(String protocol, String host, int port, String file); URL gamelan=new URL("http", "www.gamelan.com", 80, "Pages/Gamelan.network.html");

Page 61: Chapter 11 : Java 网络编程

61

创建一个 URL ( 续 )

注意:类 URL 的构造方法都声明抛弃非运行时例外( MalformedURLException ),因此生成 URL 对象时,我们必须要对这一例外进行处理,通常是用 try-catch语句进行捕获。格式如下:try{   URL myURL= new URL(…)   }catch (MalformedURLException e){  …   //exception handler code here  …   }

Page 62: Chapter 11 : Java 网络编程

62

解析一个 URL

一个 URL 对象生成后,其属性是不能被改变的,但是我们可以通过类 URL 所提供的方法来获取这些属性:public String getProtocol() 获取该 URL 的协议名。public String getHost() 获取该 URL 的主机名。public int getPort() 获取该 URL 的端口号,如果没有设置端口,返回 -1 。public String getFile() 获取该 URL 的文件名。public String getRef() 获取该 URL 在文件中的相对位置。public String getQuery() 获取该 URL 的查询信息。public String getPath() 获取该 URL 的路径public String getAuthority() 获取该 URL 的权限信息public String getUserInfo() 获得使用者的信息public String getRef() 获得该 URL 的锚

Page 63: Chapter 11 : Java 网络编程

63

1. import java.net.*;2. import java.io.*;

3. public class ParseURL {4. public static void main(String[] args) throws Exception {5. 6. URL aURL = new

URL("http://java.sun.com:80/docs/books/"7. + "tutorial/index.html#DOWNLOADING");8. System.out.println("protocol = " +

aURL.getProtocol());9. System.out.println("host = " + aURL.getHost());10. System.out.println("filename = " + aURL.getFile());11. System.out.println("port = " + aURL.getPort()); 12. System.out.println("ref = " + aURL.getRef());13. }14. }

Page 64: Chapter 11 : Java 网络编程

64

从 URL 读取WWW 网络资源

当我们得到一个 URL 对象后,就可以通过它读取指定的 WWW资源。这时我们将使用URL 的方法 openStream() ,其定义为: InputStream openStream();

方法 openSteam()与指定的 URL 建立连接并返回 InputStream 类的对象以从这一连接中读取数据。

Page 65: Chapter 11 : Java 网络编程

65

1. public class URLReader {2. public static void main(String[] args) throws Exception { 3. //声明抛出所有例外4. URL tirc = new URL("http://www.yahoo.com/"); 5. // 构建一个 URL 对象6. BufferedReader in = new BufferedReader(new

InputStreamReader(tirc.openStream()));7. // 使用 openStream 得到一个输入流,并由此构建一个 BufferedReader 对

象8. String inputLine; 9. File outfile = new File("test.html"); 10. PrintWriter out = new PrintWriter(new FileWriter(outfile));11. while ((inputLine = in.readLine()) != null) {12. // 从输入流中不断读取数据直到读完为止13. out.println(inputLine); //把读入的数据写入 test.html14. }15. in.close(); // 关闭输入流16. out.close();17. }18. }

Page 66: Chapter 11 : Java 网络编程

66

通过 URLConnetction 连接 WWW

通过 URL 的方法 openStream() ,我们只能从网络上读取数据,如果我们同时还想输出数据,例如向服务器端的 CGI 程序发送一些数据,我们必须先与 URL建立连接,然后才能对其进行读写,这时就要用到类URLConnection了。

类 URLConnection 也在包 java.net 中定义,它表示Java 程序和 URL 在网络上的通信连接。当与一个URL 建立连接时,首先要在一个 URL 对象上通过方法 openConnection()生成对应的 URLConnection 对象。

Page 67: Chapter 11 : Java 网络编程

67

下面的程序段首先生成一个指向地址 http://www.zjut.edu.cn/xyw/index.jsp 的对象,然后用openConnection ()打开该 URL 对象上的一个连接,返回一个 URLConnection 对象。如果连接过程失败,将产生 IOException.

try{ URL zjut = new URL ("http://www.zjut.edu.cn/xyw/index.jsp"); URLConnectonn tc = zjut.openConnection(); }catch(MalformedURLException e){

// 创建 URL() 对象失败  … }catch (IOException e){ //openConnection()失败  …}

Page 68: Chapter 11 : Java 网络编程

68

类 URLConnection

类 URLConnection 提供了很多方法来设置或获取连接参数,程序设计时最常使用的是getInputStream() 和 getOurputStream(), 其定义为:   InputSteram getInputSteram();   OutputSteram getOutputStream();

Page 69: Chapter 11 : Java 网络编程

69

通过返回的输入 / 输出流我们可以与远程对象进行通信

URL url =new URL (“http://www.javasoft.com/cgi-bin/backwards”); // 创建一 URL 对象

URLConnectin con=url.openConnection(); // 由 URL 对象获取 URLConnection 对象

DataInputStream dis=new DataInputStream (con.getInputSteam()); // 由 URLConnection 获取输入流,并构造 DataInputStream 对

PrintStream ps=new PrintSteam(con.getOutupSteam());// 由 URLConnection 获取输出流,并构造 PrintStream 对象

String line=dis.readLine(); //从服务器读入一行ps.println("client…"); // 向服务器写出字符串 "client…"

Page 70: Chapter 11 : Java 网络编程

70

作业

1 、使用 socket 编写一个服务器端程序,服务器端程序在端口 8888 监听,如果它接到客户端发来的“ hello” 请求时会回应一个“ hello” ,对客户端的其他请求不响应。

2 、修改支持多客户的 client/server 程序,设定客户的最大连接数是 10 ,若超出 10 则服务器给出信息“客户已达到最大连接数,请等待…”。

3 、利用 UDP 协议实现文件传输程序