import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Collections;
public class IoEchoServer implements Runnable {
// ThreadLocal<Socket> localSocket = new ThreadLocal<Socket>();
Map<String, Socket> socketMap = Collections
.synchronizedMap(new HashMap<String, Socket>());
int threadCounter = 0;
synchronized private int getCounter() {
return threadCounter++;
}
public IoEchoServer() throws IOException {
ServerSocket server = new ServerSocket(1984);
while (true) {
Socket socket = server.accept();
// happened in the main thread.
// localSocket.set(socket);
String threadName = "---Thread" + getCounter() + "---";
socketMap.put(threadName, socket);
this.start(threadName);
}
}
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
new IoEchoServer();
}
public void run() {
try {
Socket socket = socketMap.get(Thread.currentThread().getName());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//PrintWriter out = new PrintWriter(socket.getOutputStream());
String buffer = null;
while(!"END".equals(buffer)){
buffer = in.readLine();
System.out.println(buffer);
}
in.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void start(String threadName) {
new Thread(this, threadName).start();
}
}
下面这个例子采取了nio方式实现,虽然还是有阻塞部分,但是与上一个相比,效率已经大幅提高。仅仅阻塞到一个监听线程中。 Java代码
package com.cxz.nio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Iterator;
import java.util.Set;
public class NioEchoServer {
private static Selector roller = null;
private static final int port = 8080;
private static NioEchoServer instance = null;
private ThreadLocal<StringBuffer> stringLocal = new ThreadLocal<StringBuffer>();
private NioEchoServer() throws IOException {
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.socket().bind(new InetSocketAddress(port));
serverChannel.configureBlocking(false);
serverChannel.register(roller, SelectionKey.OP_ACCEPT);
}
public synchronized static NioEchoServer getInstance() throws IOException {
if (instance == null) {
roller = Selector.open();
instance = new NioEchoServer();
}
return instance;
}
public void start() throws IOException {
int keyAdded = 0;
while ((keyAdded = roller.select()) > 0) {
Set<SelectionKey> keySets = roller.selectedKeys();
Iterator iter = keySets.iterator();
while (iter.hasNext()) {
SelectionKey key = (SelectionKey) iter.next();
iter.remove();
actionHandler(key);
}
}
}
public void actionHandler(SelectionKey key) throws IOException {
if (key.isAcceptable()) {
ServerSocketChannel serverChannel = (ServerSocketChannel) key
.channel();
SocketChannel socketChannel = serverChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(roller, SelectionKey.OP_READ);
} else if (key.isReadable()) {
ByteBuffer buffer = ByteBuffer.allocate(16);
SocketChannel socketChannel = (SocketChannel) key.channel();
socketChannel.read(buffer);
buffer.flip();
String temp = decode(buffer);
StringBuffer strBuffer = stringLocal.get();
if (strBuffer == null) {
strBuffer = new StringBuffer();
}
strBuffer.append(temp);
if (temp.equals("\r\n")) {
System.out.println(strBuffer.toString());
strBuffer = null;
}
stringLocal.set(strBuffer);
}
}
public String decode(ByteBuffer buffer) {
Charset charset = null;
CharsetDecoder decoder = null;
CharBuffer charBuffer = null;
try {
charset = Charset.forName("UTF-8");
decoder = charset.newDecoder();
charBuffer = decoder.decode(buffer);
return charBuffer.toString();
} catch (Exception ex) {
ex.printStackTrace();
return "";
}
}
public static void main(String[] args) {
try {
NioEchoServer.getInstance().start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}