代码下载: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对象中得到输入流与输出流,再接收和发送数据。