当前位置:七道奇文章资讯编程技术Java编程
日期:2011-03-22 16:16:00  来源:本站整理

服务多个客户(java)[Java编程]

赞助商链接



  本文“服务多个客户(java)[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
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.net.*;

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:
    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();
    }
  } 
} ///:~

每次有新客户恳求成立一个衔接时,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.net.*;
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()));
      // 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(IOException 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);
    }
  }
} ///:~

JabberClientThread构建器获得一个InetAddress,并用它翻开一个套接字.大家大概已看出了这样的一个套路:Socket必定用于成立某种Reader以及/大概Writer(大概InputStream和/或OutputStream)对象,这是应用Socket的唯一方法(当然,我们可考虑编写1、两个类,令其自动完成这些操作,避免大量反复的代码编写工作).一样地,start()履行线程的初始化,并调用run().在这里,消息发送给服务器,而来自服务器的信息则在屏幕上回显出来.但是,线程的“存在时间”是有限的,终究城市完毕.注意在套接字成立好今后,但在构建器完成之前,假如构建器失利,套接字会被排除.不然,为套接字调用close()的责任便落到了run()办法的头上.
threadcount跟踪计算目前存在的JabberClientThread对象的数目.它将作为构建器的一部份增值,并在run()退出时减值(run()退出意味着线程中止).在MultiJabberClient.main()中,大家可以看到线程的数目会得到查抄.若数目太多,则多余的暂时不成立.办法随后进入“休眠”状况.这样一来,一旦部份线程最后被中止,多作的那些线程便可以成立了.大家可试验一下渐渐增大MAX_THREADS,看看关于你利用的系统来说,成立多少线程(衔接)才会使您的系统资源降低到危险程度.
  以上是“服务多个客户(java)[Java编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
  • 服务多个客户(java)
  • 本文地址: 与您的QQ/BBS好友分享!
    • 好的评价 如果您觉得此文章好,就请您
        0%(0)
    • 差的评价 如果您觉得此文章差,就请您
        0%(0)

    文章评论评论内容只代表网友观点,与本站立场无关!

       评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
    Copyright © 2020-2022 www.xiamiku.com. All Rights Reserved .