资料整理

 

网络编程

   1. 什么是 TCP/ IP 协议?
   2. TCP/IP 有哪两种传输协议 , 各有什么特点?
   3. 什么是 URL
   4. URL IP 地址有什么样的关系?
   5. 什么叫套接字( Socket )?
   6. 套接字( Socket )和 TCP/IP 协议的关系?
   7. URL 和套接字( Socket )的关系?
8.1 网络编程基本概念,TCP/IP协议简介

8.1.1 网络基础知识

网络编程的目的就是指直接或间接地通过网络协议与其他计算机进行通讯。网络编程中有两个主要的问题,一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输。在 TCP/IP 协议中 IP 层主要负责网络主机的定位,数据传输的路由,由 IP 地址可以唯一地确定 Internet 上的一台主机。而 TCP 层则提供面向应用的可靠的或非可靠的数据传输机制,这是网络编程的主要对象,一般不需要关心 IP 层是如何处理数据的。
   目前较为流行的网络编程模型是客户机 / 服务器( C/S )结构。即通信双方一方作为服务器等待客户提出请求并予以响应。客户则在需要服务时向服务器提出申请。服务器一般作为守护进程始终运行,监听网络端口,一旦有客户请求,就会启动一个服务进程来响应该客户,同时自己继续监听服务端口,使后来的客户也能及时得到服务。

8.1.3两类传输协议:TCP;UDP
   尽管 TCP/IP 协议的名称中只有 TCP 这个协议名,但是在 TCP/IP 的传输层同时存在 TCP UDP 两个协议。

TCP Tranfer Control Protocol 的简称,是一种面向连接的保证可靠传输的协议。 通过 TCP 协议传输,得到的是一个顺序的无差错的数据流。发送方和接收方的成对的两个 socket 之间必须建立连接,以便在 TCP 协议的基础上进行通信,当一个 socket (通常都是 server socket )等待建立连接时,另一个 socket 可以要求进行连接,一旦这两个 socket 连接起来,它们就可以进行双向数据传输,双方都可以进行发送或接收操作。
   UDP User Datagram Protocol 的简称,是一种无连接的协议, 每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。
  下面我们对这两种协议做简单比较:
   使用 UDP 时,每个数据报中都给出了完整的地址信息,因此无需要建立发送方和接收方的连接。对于 TCP 协议,由于它是一个面向连接的协议,在 socket 之间进行数据传输之前必然要建立连接,所以在 TCP 中多了一个连接建立的时间。
 
  使用 UDP 传输数据时是有大小限制的,每个被传输的数据报必须限定在 64KB 之内。而 TCP 没有这方面的限制,一旦连接建立起来,双方的 socket 就可以按统一的格式传输大量的数据。 UDP 是一个不可靠的协议,发送方所发送的数据报并不一定以相同的次序到达接收方。而 TCP 是一个可靠的协议,它确保接收方完全正确地获取发送方所发送的全部数据。
   总之, TCP 在网络通信上有极强的生命力,例如远程连接( Telnet )和文件传输( FTP )都需要不定长度的数据被可靠地传输。相比之下 UDP 操作简单,而且仅需要较少的监护,因此通常用于局域网高可靠性的分散系统中 client/server 应用程序。
   读者可能要问,既然有了保证可靠传输的 TCP 协议,为什么还要非可靠传输的 UDP 协议呢?主要的原因有两个。一是可靠的传输是要付出代价的,对数据内容正确性的检验必然占用计算机的处理时间和网络的带宽,因此 TCP 传输的效率不如 UDP 高。二是在许多应用中并不需要保证严格的传输可靠性,比如视频会议系统,并不要求音频视频数据绝对的正确,只要保证连贯性就可以了,这种情况下显然使用 UDP 会更合理一些。

8.2 基于URL的高层次Java网络编程

8.2.1一致资源定位器URL

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

8.2.2 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 协议名 :// 机器名+端口号+文件名+内部引用 .

8.2.3 创建一个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")
  (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");

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

try{
      URL myURL= new URL(…)
   }catch (MalformedURLException e){
      }

8.2.4 解析一个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 的锚

8.2.5 从URL读取WWW网络资源

当我们得到一个 URL 对象后,就可以通过它读取指定的 WWW 资源。这时我们将使用 URL 的方法 openStream() ,其定义为:
          InputStream openStream();
  
  方法 openSteam() 与指定的 URL 建立连接并返回 InputStream 类的对象以从这一连接中读取数据。
   public class URLReader {
   public static void main(String[] args) throws Exception {
                       // 声明抛出所有例外
     URL tirc = new URL("http://www.tirc1.cs.tsinghua.edu.cn/");
                       // 构建一 URL 对象
     BufferedReader in = new BufferedReader(new InputStreamReader(tirc.openStream()));
     // 使用 openStream 得到一输入流并由此构造一个 BufferedReader 对象
     String inputLine;
     while ((inputLine = in.readLine()) != null)
                  // 从输入流不断的读数据,直到读完为止
        System.out.println(inputLine); // 把读入的数据打印到屏幕上
     in.close(); // 关闭输入流
   }
   }

8.2.6 通过URLConnetction连接WWW

通过 URL 的方法 openStream() ,我们只能从网络上读取数据,如果我们同时还想输出数据,例如向服务器端的 CGI 程序发送一些数据,我们必须先与 URL 建立连接,然后才能对其进行读写,这时就要用到类 URLConnection 了。 CGI 是公共网关接口( Common Gateway Interface )的简称,它是用户浏览器和服务器端的应用程序进行连接的接口,有关 CGI 程序设计,请读者参考有关书籍。
   URLConnection 也在包 java.net 中定义,它表示 Java 程序和 URL 在网络上的通信连接。当与一个 URL 建立连接时,首先要在一个 URL 对象上通过方法 openConnection() 生成对应的 URLConnection 对象。例如下面的程序段首先生成一个指向地址 http://edu.chinaren.com/index.shtml 的对象,然后用 openConnection ()打开该 URL 对象上的一个连接,返回一个 URLConnection 对象。如果连接过程失败,将产生 IOException.
   Try{
     URL netchinaren = new URL ("http://edu.chinaren.com/index.shtml");
     URLConnectonn tc = netchinaren.openConnection();
   }catch(MalformedURLException e){ // 创建 URL() 对象失败
  
   }catch (IOException e){ //openConnection() 失败
  
   }
   类 URLConnection 提供了很多方法来设置或获取连接参数,程序设计时最常使用的是 getInputStream() getOurputStream(), 其定义为:
      InputSteram getInputSteram();
      OutputSteram getOutputStream();
   通过返回的输入 / 输出流我们可以与远程对象进行通信。看下面的例子:
   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…"
    其中 backwards 为服务器端的 CGI 程序。实际上,类 URL 的方法 openSteam ()是通过 URLConnection 来实现的。它等价于
     openConnection().getInputStream();
   基于 URL 的网络编程在底层其实还是基于下面要讲的 Socket 接口的。 WWW FTP 等标准化的网络服务都是基于 TCP 协议的,所以本质上讲 URL 编程也是基于 TCP 的一种应用 .

8.3 基于Socket的低层次Java网络编程

8.3.1 Socket通讯

网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个 Socket Socket 通常用来实现客户方和服务方的连接。 Socket TCP/IP 协议的一个十分流行的编程界面,一个 Socket 由一个 IP 地址和一个端口号唯一确定。
  在传统的 UNIX 环境下可以操作 TCP/IP 协议的接口不止 Socket 一个, Socket 所支持的协议种类也不光 TCP/IP 一种,因此两者之间是没有必然联系的。在 Java 环境下, Socket 编程主要是指基于 TCP/IP 协议的网络编程。

8.3.2 Socket通讯的一般过程

使用 Socket 进行 Client/Server 程序设计的一般连接过程是这样的: Server Listen( 监听 ) 某个端口是否有连接请求, Client 端向 Server 端发出 Connect( 连接 ) 请求, Server 端向 Client 端发回 Accept (接受)消息。一个连接就建立起来了。 Server 端和 Client 端都可以通过 Send Write 等方法与对方通信。

对于一个功能齐全的 Socket ,都要包含以下基本结构,其工作过程包含以下四个基本的步骤:
  ( 1 创建 Socket
  ( 2 打开连接到 Socket 的输入 / 出流;
  ( 3 按照一定的协议对 Socket 进行读 / 写操作;
  ( 4 关闭 Socket.

8.3.3 创建Socket

java 在包 java.net 中提供了两个类 Socket ServerSocket ,分别用来表示双向连接的客户端和服务端 。这是两个封装得非常好的类,使用很方便。其构造方法如下:
   Socket(InetAddress address, int port);
   Socket(InetAddress address, int port, boolean stream);
   Socket(String host, int prot);
   Socket(String host, int prot, boolean stream);
   Socket(SocketImpl impl)
   Socket(String host, int port, InetAddress localAddr, int localPort)
   Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
   ServerSocket(int port);
   ServerSocket(int port, int backlog);
   ServerSocket(int port, int backlog, InetAddress bindAddr)
   其中 address host port 分别是双向连接中另一方的 IP 地址、主机名和端口号, stream 指明 socket 是流 socket 还是数据报 socket localPort 表示本地主机的端口号, localAddr bindAddr 是本地机器的地址( ServerSocket 的主机地址), impl socket 的父类,既可以用来创建 serverSocket 又可以用来创建 Socket count 则表示服务端所能支持的最大连接数。例如:
    Socket client = new Socket("127.0.01.", 80);
   ServerSocket server = new ServerSocket(80);
   注意,在选择端口时,必须小心。每一个端口提供一种特定的服务,只有给出正确的端口,才能获得相应的服务。 0~1023 的端口号为系统所保留,例如 http 服务的端口号为 80,telnet 服务的端口号为 21,ftp 服务的端口号为 23, 所以我们在选择端口号时,最好选择一个大于 1023 的数以防止发生冲突。
   在创建 socket 时如果发生错误,将产生 IOException ,在程序中必须对之作出处理。所以在创建 Socket ServerSocket 是必须捕获或抛出例外。

8.3.8 简单的Client/Server程序设计

下面我们给出一个用 Socket 实现的客户和服务器交互的典型的 C/S 结构的演示程序,读者通过仔细阅读该程序,会对前面所讨论的各个概念有更深刻的认识。程序的意义请参考注释。

1. 客户端程序
  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);
//出错,则打印出错信息
      }
  }
}

 2. 服务器端程序
  import java.io.*;
  import java.net.*;
  import java.applet.Applet;
  public class TalkServer{
    public static void main(String args[]) {
      try{
        ServerSocket server=null;
        try{
          server=new ServerSocket(4700);
        
//创建一个ServerSocket在端口4700监听客户请求
        }catch(Exception e) {
          System.out.println("can not listen to:"+e);
        
//出错,打印出错信息
        }

         Socket socket=null;
        try{
          socket=server.accept();
          
//使用accept()阻塞等待客户请求,有客户
          //请求到来则产生一个Socket对象,并继续执行

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

8.3.9 支持多客户的 client/server 程序设计

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

ServerSocket serverSocket=null;
     boolean listening=true;
     try{
       serverSocket=new ServerSocket(4700);
       // 创建一个 ServerSocket 在端口 4700 监听客户请求
     }catch(IOException e) {    }
     while(listening){ // 永远循环监听
        new ServerThread(serverSocket.accept(),clientnum).start();
       // 监听到客户请求,根据得到的 Socket 对象和
       客户计数创建服务线程,并启动之
       clientnum++; // 增加客户计数
     }
     serverSocket.close(); // 关闭 ServerSocket

设计 ServerThread

  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{// 在这里实现数据的接受和发送 }

8.3.10 据报 Datagram 通讯

前面在介绍 TCP/IP 协议的时候,我们已经提到,在 TCP/IP 协议的传输层除了 TCP 协议之外还有一个 UDP 协议,相比而言 UDP 的应用不如 TCP 广泛,几个标准的应用层协议 HTTP FTP SMTP… 使用的都是 TCP 协议。但是,随着计算机网络的发展, UDP 协议正越来越来显示出其威力,尤其是在需要很强的实时交互性的场合,如网络游戏,视频会议等, UDP 更是显示出极强的威力,下面我们就介绍一下 Java 环境下如何实现 UDP 网络传输。

8.3.11 什么是 Datagram

所谓数据报( Datagram )就跟日常生活中的邮件系统一样,是不能保证可靠的寄到的,而面向链接的 TCP 就好比电话,双方能肯定对方接受到了信息。在本章前面,我们已经对 UDP TCP 进行了比较,在这里再稍作小节:
   TCP ,可靠,传输大小无限制,但是需要连接建立时间,差错控制开销大。
   UDP ,不可靠,差错控制开销较小,传输大小限制在 64K 以下,不需要建立连接。

8.3.12 Datagram 通讯的表示方法: DatagramSocket DatagramPacket

java.net 中提供了两个类 DatagramSocket DatagramPacket 用来支持数据报通信, DatagramSocket 用于在程序之间建立传送数据报的通信连接, DatagramPacket 则用来表示一个数据报。 先来看一下 DatagramSocket 的构造方法:
    DatagramSocket ();
    DatagramSocket int prot ;
    DatagramSocket(int port, InetAddress laddr)
      其中, port 指明 socket 所使用的端口号,如果未指明端口号,则把 socket 连接到本地主机上一个可用的端口。 laddr 指明一个可用的本地地址。给出端口号时要保证不发生端口冲突,否则会生成 SocketException 类例外。注意:上述的两个构造方法都声明抛弃非运行时例外 SocketException ,程序中必须进行处理,或者捕获、或者声明抛弃。
  
用数据报方式编写 client/server 程序时,无论在客户方还是服务方,首先都要建立一个 DatagramSocket 对象,用来接收或发送数据报,然后使用 DatagramPacket 类对象作为传输数据的载体。 下面看一下 DatagramPacket 的构造方法
    DatagramPacket byte buf[],int length );
    DatagramPacket(byte buf[], int length, InetAddress addr, int port);
    DatagramPacket(byte[] buf, int offset, int length)
    DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)

  其中, buf 中存放数据报数据, length 为数据报中数据的长度, addr port 旨明目的地址, offset 指明了数据报的位移量。
   在接收数据前,应该采用上面的第一种方法生成一个 DatagramPacket 对象,给出接收数据的缓冲区及其长度。然后调用 DatagramSocket 的方法 receive() 等待数据报的到来, receive() 将一直等待,直到收到一个数据报为止。
   DatagramPacket packet=new DatagramPacket(buf, 256);
   Socket.receive (packet);
   发送数据前,也要先生成一个新的 DatagramPacket 对象,这时要使用上面的第二种构造方法,在给出存放发送数据的缓冲区的同时,还要给出完整的目的地址,包括 IP 地址和端口号。发送数据是通过 DatagramSocket 的方法 send() 实现的, send() 根据数据报的目的地址来寻径,以传递数据报。
   DatagramPacket packet=new DatagramPacket(buf, length, address, port);
   Socket.send(packet)
   
在构造数据报时,要给出 InetAddress 类参数。类 InetAddress 在包 java.net 中定义,用来表示一个 Internet 地址,我们可以通过它提供的类方法 getByName ()从一个表示主机名的字符串获取该主机的 IP 地址,然后再获取相应的地址信息。

8.3.14 用数据报进行广播通讯

DatagramSocket 只允许数据报发送一个目的地址, java.net 包中提供了一个类 MulticastSocket ,允许数据报以广播方式发送到该端口的所有客户。 MulticastSocket 用在客户端,监听服务器广播来的数据。

1. 客户方程序 :MulticastClient.java
  import java.io.*;
  import java.net.*;
  import java.util.*;
  public class MulticastClient {
    public static void main(String args[]) throws IOException
    {
     MulticastSocket socket=new MulticastSocket(4446);
     
//创建4446端口的广播套接字
     InetAddress address=InetAddress.getByName("230.0.0.1");
     
//得到230.0.0.1的地址信息
     socket.joinGroup(address);
     
//使用joinGroup()将广播套接字绑定到地址上
     DatagramPacket packet;

      for(int i=0;i<5;i++) {
       byte[] buf=new byte[256];
       
//创建缓冲区

       packet=new DatagramPacket(buf,buf.length);
       
//创建接收数据报
       socket.receive(packet);
//接收
       String received=new String(packet.getData());
       
//由接收到的数据报得到字节数组,
       
//并由此构造一个String对象
       System.out.println("Quote of theMoment:"+received);
       
//打印得到的字符串
     }
//循环5次
     socket.leaveGroup(address);
     
//把广播套接字从地址上解除绑定
     socket.close();
//关闭广播套接字
   }
 }

 2. 服务器方程序:MulticastServer.java
  public class MulticastServer{
    public static void main(String args[]) throws java.io.IOException
    {
      new MulticastServerThread().start();
      
//启动一个服务器线程
    }
  }

 3. 程序MulticastServerThread.java
  import java.io.*;
  import java.net.*;
  import java.util.*;
  public class MulticastServerThread extends QuoteServerThread
  
//从QuoteServerThread继承得到新的服务器线程类MulticastServerThread
  {
    Private long FIVE_SECOND=5000;
//定义常量,5秒钟
    public MulticastServerThread(String name) throws IOException
    {
      super("MulticastServerThread");
      
//调用父类,也就是QuoteServerThread的构造函数
    }

    public void run() //重写父类的线程主体
    {
     while(moreQuotes) {
     
//根据标志变量判断是否继续循环
      try{
        byte[] buf=new byte[256];
        
//创建缓冲区
        String dString=null;
        if(in==null) dString=new Date().toString();
        
//如果初始化的时候打开文件失败了,
        //则使用日期作为要传送的字符串

        else dString=getNextQuote();
        
//否则调用成员函数从文件中读出字符串
        buf=dString.getByte();
        
//把String转换成字节数组,以便传送send it
        InetAddress group=InetAddress.getByName("230.0.0.1");
        
//得到230.0.0.1的地址信息
        DatagramPacket packet=new DatagramPacket(buf,buf.length,group,4446);
        
//根据缓冲区,广播地址,和端口号创建DatagramPacket对象
        socket.send(packet);
//发送该Packet
        try{
          sleep((long)(Math.random()*FIVE_SECONDS));
          
//随机等待一段时间,0~5秒之间
        }catch(InterruptedException e) { }
//异常处理
      }catch(IOException e){
//异常处理
        e.printStackTrace( );
//打印错误栈

        moreQuotes=false; //置结束循环标志
      }
    }
    socket.close( );
//关闭广播套接口
   }
 }

【本讲小结】

本讲主要讲解了 Java 环境下的网络编程。因为 TCP/IP 协议是 Java 网络编程的基础知识,本讲开篇重点介绍了 TCP/IP 协议中的一些概念, TCP/IP 协议本身是一个十分庞大的系统,用几个小节是不可能讲清楚的。所以我们只是联系实际,讲解了一些最基本的概念,帮助学生理解后面的相关内容。重点有一下几个概念:主机名, IP ,端口,服务类型, TCP UDP
   后续的内容分为两大块,一块是以 URL 为主线,讲解如何通过 URL 类和 URLConnection 类访问 WWW 网络资源,由于使用 URL 十分方便直观,尽管功能不是很强,还是值得推荐的一种网络编程方法,尤其是对于初学者特别容易接受。本质上讲, URL 网络编程在传输层使用的还是 TCP 协议。
   另一块是以 Socket 接口和 C/S 网络编程模型为主线,依次讲解了如何用 Java 实现基于 TCP C/S 结构,主要用到的类有 Socket ServerSocket 。以及如何用 Java 实现基于 UDP C/S 结构,还讨论了一种特殊的传输方式,广播方式,这种方式是 UDP 所特有的,主要用到的类有 DatagramSocket , DatagramPacket, MulticastSocket 。这一块在 Java 网络编程中相对而言是最难的(尽管 Java 在网络编程这方面已经做的够 " 傻瓜 " 了,但是网络编程在其他环境下的却是一件极为头痛的事情,再 " 傻瓜 " 还是有一定的难度),也是功能最为强大的一部分 , 读者应该好好研究,领悟其中的思想。
   最后要强调的是要学好 Java 网络编程, Java 语言,最重要的还是在于多多练习!

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=102420

posted on 2006-07-15 13:39 谢玮 阅读(202) 评论(0)  编辑  收藏 所属分类: java应用程序


只有注册用户登录后才能发表评论。


网站导航:
 

导航

统计

常用链接

留言簿(1)

随笔档案

文章分类

文章档案

搜索

最新评论