代码下载:http://pan.baidu.com/s/1ntEyLML
下面是一个阻塞线程服务器的代码例子。
EchoServer
package block; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.logging.Handler; import java.util.logging.LogRecord; public class EchoServer { private int port = 8000; private ServerSocketChannel serverSocketChannel = null; private ExecutorService executorService; private static final int POOL_MULTIPLE = 4; public EchoServer() throws IOException { // 创建一个线程池 executorService = Executors.newFixedThreadPool(Runtime.getRuntime() .availableProcessors() * POOL_MULTIPLE); // 创建一个ServerSocketChannel对象 serverSocketChannel = ServerSocketChannel.open(); // 使得在同一个主机上关闭了服务器程序,紧接着再启动该服务器程序时,可以顺利绑定相同的端口。 serverSocketChannel.socket().setReuseAddress(true); // 把服务器进程与一个本地端口绑定 serverSocketChannel.socket().bind(new InetSocketAddress(port)); System.out.print("Service Start"); } public void service() { while (true) { SocketChannel socketChannel = null; try { socketChannel = serverSocketChannel.accept(); //处理客户连接 executorService.execute(new Handler(socketChannel)); } catch (IOException e) { // TODO: handle exception e.printStackTrace(); } } } public static void main(String args[]) throws IOException { new EchoServer().service(); } //处理客户连接 class Handler implements Runnable { private SocketChannel socketChannel; public Handler(SocketChannel socketChannel) { this.socketChannel = socketChannel; } @Override public void run() { // TODO Auto-generated method stub handle(socketChannel); } public void handle(SocketChannel socketChannel) { try { //获得与socketChannel关联的Socket对象 Socket socket = socketChannel.socket(); System.out.println("接收到客户连接,来自:" + socket.getInetAddress() + ":" + socket.getPort()); BufferedReader br = getReader(socket); PrintWriter pw = getWriter(socket); String msg = null; while ((msg = br.readLine()) != null) { System.out.println(msg); pw.println(echo(msg)); if (msg.equals("bye")) break; } } catch (IOException e) { // TODO: handle exception e.printStackTrace(); }finally{ try { if (socketChannel != null) socketChannel.close(); } catch (IOException e2) { // TODO: handle exception e2.printStackTrace(); } } } private PrintWriter getWriter(Socket socket) throws IOException { OutputStream socketOut = socket.getOutputStream(); return new PrintWriter(socketOut,true); } private BufferedReader getReader(Socket socket) throws IOException { InputStream socketIn = socket.getInputStream(); return new BufferedReader(new InputStreamReader(socketIn)); } public String echo(String msg) { return "echo:" + msg; } } }
EchoServer类的构造方法负责创建线程池,启动服务器,把它绑定到一个本地端口。EchoServer类的service()方法负责接收客户的连接。每接收到一个客户连接,就把它交给线程来处理,线程池取出一个空闲的线程,来执行Handler对象的run()方法。Handler类的handler()方法负责与客户端通信。该方法先获得与SocketChannel关联的Socket对象,然后从Socket对象中得到输入流与输出流,再接收和发送数据。