友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
一世书城 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

Java编程思想第4版[中文版](PDF格式)-第175章

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!






JabberServer 可以正常工作,但每次只能为一个客户程序提供服务。在典型的服务器中,我们希望同时能处 

理多个客户的请求。解决这个问题的关键就是多线程处理机制。而对于那些本身不支持多线程的语言,达到 

这个要求无疑是异常困难的。通过第 14 章的学习,大家已经知道Java 已对多线程的处理进行了尽可能的简 

化。由于Java 的线程处理方式非常直接,所以让服务器控制多名客户并不是件难事。  

最基本的方法是在服务器(程序)里创建单个 ServerSocket,并调用accept()来等候一个新连接。一旦 

accept()返回,我们就取得结果获得的 Socket,并用它新建一个线程,令其只为那个特定的客户服务。然后 

再调用 accept() ,等候下一次新的连接请求。  

对于下面这段服务器代码,大家可发现它与JabberServer。java 例子非常相似,只是为一个特定的客户提供 

服务的所有操作都已移入一个独立的线程类中:  

  

//: MultiJabberServer。java  

// A server that uses multithreading to handle   

// any number of clients。  

import java。io。*;  

import java。*;  

  

class ServeOneJabber extends Thread {  

  private Socket socket;  

  private BufferedReader in;  

  private PrintWriter out;  

  public ServeOneJabber(Socket s)   

      throws IOException {  

    socket = s;  

    in =   

      new BufferedReader(  

        new InputStreamReader(  

          socket。getInputStream()));  

    // Enable auto…flush:  



                                                                               543 


…………………………………………………………Page 545……………………………………………………………

    out =   

      new PrintWriter(  

        new BufferedWriter(  

          new OutputStreamWriter(  

            socket。getOutputStream())); true);  

    // If any of the above calls throw an   

    // exception; the caller is responsible for  

    // closing the socket。 Otherwise the thread  

    // will close it。  

    start(); // Calls run()  

  }  

  public void run() {  

    try {  

      while (true) {    

        String str = in。readLine();  

        if (str。equals(〃END〃)) break;  

        System。out。println(〃Echoing: 〃 + str);  

        out。println(str);  

      }  

      System。out。println(〃closing。。。〃);  

    } catch (IOException e) {  

    } finally {  

      try {  

        socket。close();  

      } catch(IOException e) {}  

    }  

  }  

}  

  

public class MultiJabberServer {    

  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) {  

        // Blocks until a connection occurs:  

        Socket socket = s。accept();  

        try {  

          new ServeOneJabber(socket);  

        } catch(IOException e) {  

          // If it fails; close the socket;  

          // otherwise the thread will close it:  

          socket。close();  

        }  

      }  

    } finally {  

      s。close();  

    }  

  }   



                                                                                             544 


…………………………………………………………Page 546……………………………………………………………

} ///:~  

  

每次有新客户请求建立一个连接时,ServeOneJabber 线程都会取得由accept()在 main() 中生成的Socket 对 

象。然后和往常一样,它创建一个 BufferedReader,并用Socket 自动刷新PrintWriter 对象。最后,它调 

用Thread 的特殊方法 start(),令其进行线程的初始化,然后调用run()。这里采取的操作与前例是一样 

的:从套扫字读入某些东西,然后把它原样反馈回去,直到遇到一个特殊的〃END〃结束标志为止。  

同样地,套接字的清除必须进行谨慎的设计。就目前这种情况来说,套接字是在ServeOneJabber 外部创建 

的,所以清除工作可以“共享”。若ServeOneJabber 构建器失败,那么只需向调用者“掷”出一个违例即 

可,然后由调用者负责线程的清除。但假如构建器成功,那么必须由 ServeOneJabber 对象负责线程的清除, 

这是在它的 run()里进行的。  

请注意MultiJabberServer 有多么简单。和以前一样,我们创建一个 ServerSocket,并调用accept()允许一 

个新连接的建立。但这一次,accept() 的返回值(一个套接字)将传递给用于ServeOneJabber 的构建器,由 

它创建一个新线程,并对那个连接进行控制。连接中断后,线程便可简单地消失。  

如果ServerSocket 创建失败,则再一次通过 main()掷出违例。如果成功,则位于外层的 try…finally代码 

块可以担保正确的清除。位于内层的try…catch 块只负责防范 ServeOneJabber 构建器的失败;若构建器成 

功,则 ServeOneJabber 线程会将对应的套接字关掉。  

为了证实服务器代码确实能为多名客户提供服务,下面这个程序将创建许多客户(使用线程),并同相同的 

服务器建立连接。每个线程的“存在时间”都是有限的。一旦到期,就留出空间以便创建一个新线程。允许 

创建的线程的最大数量是由final int maxthreads 决定的。大家会注意到这个值非常关键,因为假如把它设 

得很大,线程便有可能耗尽资源,并产生不可预知的程序错误。  

  

//: MultiJabberClient。java  

// Client that tests the MultiJabberServer  

// by starting up multiple clients。  

import java。*;  

import java。io。*;  

  

class JabberClientThread extends Thread {  

  private Socket socket;  

  private BufferedReader in;  

  private PrintWriter out;  

  private static int counter = 0;  

  private int id = counter++;  

  private static int threadcount = 0;  

  public static int threadCount() {   

    return threadcount;   

  }  

  public JabberClientThread(InetAddress addr) {  

    System。out。println(〃Making client 〃 + id);  

    threadcount++;  

    try {  

      socket =   

        new Socket(addr; MultiJabberServer。PORT);  

    } catch(IOException e) {  

      // If the creation of the socket fails;   

      // nothing needs to be cleaned up。  

    }  

    try {      

      in =   

        new BufferedReader(  

          new InputStreamReader(  

            socket。getInputStream()));  



                                                                                          545 


…………………………………………………………Page 547……………………………………………………………

      // Enable auto…flush:  

      out =   

        new PrintWriter(  

          new BufferedWriter(  

            new OutputStreamWriter(  

              socket。getOutputStream())); true);  

      start();  

    } catch(IOException e) {  

      // The socket should be closed on any   

      // failures other than the socket   

      // constructor:  

      try {  

        socket。close();  

      } catch(IOException e2) {}  

    }  

    // Otherwise the socket will be closed by  

    // the run() method of the thread。  

  }  

  public void run() {  

    try {  

      for(int i = 0; i 《 25; i++) {  

        out。println(〃Client 〃 + id + 〃: 〃 + i);  

        String str = in。readLine();  

        System。out。println(str);  

      }  

      out。println(〃END〃);  

    } catch(IOException e) {  

    } finally {  

      // Always close it:  

      try {  

        socket。close();  

      } catch(IOExcept ion e) {}  

      threadcount…; // Ending this thread  

    }  

  }  

}  

  

public class MultiJabberClient {  

  static final int MAX_THREADS = 40;  

  public static void main(String'' args)   

      throws IOException; InterruptedException {  

    InetAddress addr =   

      InetAddress。getByName(null);  

    while(true) {  

      if(JabberClientThread。threadCount()   

         《 MAX_THREADS)  

        new JabberClientThread(addr);  

      Thread。currentThread()。sleep(100);  

    }  

  }  

} ///:~  

  



                                                                                             546 


…………………………………………………………Page 548……………………………………………………………

JabberClientThread 构建器获取一个 InetAddress,并用它打开一个套接字。大家可能已看出了这样的一个 

套路:Socket 肯定用于创建某种 Reader 以及/或者Writer (或者InputStream和/或 OutputStream)对 

象,这是运用Socket 的唯一方式(当然,我们可考虑编写一、两个类,令其自动完成这些操作,避免大量重 

复的代码编写工作)。同样地,start()执行线程的初始化,并调用run()。在这里,消息发送给服务器,而 

来自服务器的信息则在屏幕上回显出来。然而,线程的“存在时间”是有限的,最终都会结束。注意在套接 

字创建好以后,但在构建
返回目录 上一页 下一页 回到顶部 0 0
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!