最近在看dubbo源码,觉得dubbo还是设计很优秀。有个想法模拟dubbo去写一个SOA框架。编写SOA框架,首先要解决底层传输问题,虽然dubbo默认是用netty传输,但是也是基于NIO。所以我自己写了NIO编程实例,开始研究SOA之路。

实现功能很简单,client发送消息给server,server接收后又发消息给client。

server端:

public class NIOServer extends Thread {
private Selector selector;
private int port;
public NIOServer() {
}
public NIOServer(int port) throws IOException {
this.port = port;
}
public void run() {
System.out.println("服务端线程已经启动!");
try {
while (selector.select() > 0) {
Set<SelectionKey> selectionKeySet = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeySet.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
try {
if (key.isAcceptable()) {
doAccept(key);
}
if (key.isReadable()) {
doRead(key);
}
if (key.isWritable()) {
doWrite(key);
}
} catch (ClosedSelectorException cek) {
cek.printStackTrace();
} catch (CancelledKeyException ck) {
ck.printStackTrace();
key.cancel();
} catch (Throwable e) {
e.printStackTrace();
}
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(selector != null){
selector.close();
}
} catch (Throwable e) {
e.printStackTrace();
}
}
private void doAccept(SelectionKey key) throws IOException {
System.out.println("accept...");
ServerSocketChannel server = (ServerSocketChannel) key.channel();
SocketChannel channel = server.accept();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ);
}
private void doRead(SelectionKey key) throws IOException {
System.out.println("read data from client...");
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
try {
while (channel.read(buffer) > 0) {
buffer.flip();
System.out.println(getString(buffer));
buffer.clear();
}
channel.register(selector, SelectionKey.OP_WRITE);
} catch (Throwable e) {
e.printStackTrace();
key.cancel();
}
}
private void doWrite(SelectionKey key) throws IOException {
System.out.println("write data to client...");
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.wrap(new String("Hi, client").getBytes("UTF-8"));
try {
while (buffer.hasRemaining()) {
channel.write(buffer);
}
channel.register(selector, SelectionKey.OP_READ);
} catch (Throwable e) {
e.printStackTrace();
key.cancel();
}
}
public void initServer(int port) throws IOException {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.bind(new InetSocketAddress(port));
selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
}
public void stopServer() throws IOException {
if (!selector.isOpen()) {
selector.close();
}
}
public static void main(String[] args) throws IOException {
NIOServer server = new NIOServer();
try {
server.initServer(8859);
server.start();
} catch (Exception e) {
e.printStackTrace();
server.stopServer();
}
}
}

client端:

public class NIOClient extends Thread {
private Selector selector;
private void initClient(int port) throws IOException {
InetSocketAddress address = new InetSocketAddress(port);
selector = Selector.open();
SocketChannel channel = SocketChannel.open();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_CONNECT);
channel.connect(address);
}
public void run() {
System.out.println("客户端已经启动!");
try {
while (selector.select() > 0) {
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iterator = keys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
if (key.isConnectable()) {
SocketChannel channel = (SocketChannel) key.channel();
// 如果正在连接,则完成连接
if (channel.isConnectionPending()) {
channel.finishConnect();
}
channel.register(selector, SelectionKey.OP_WRITE);
}
if (key.isReadable()) {
doRead(key);
}
if(key.isWritable()){
doWrite(key);
}
}
}
} catch (ClosedChannelException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void doRead(SelectionKey key) throws IOException {
System.out.println("read data from server...");
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (channel.read(buffer) > 0) {
buffer.flip();
System.out.println(getString(buffer));
buffer.clear();
}
channel.register(selector, SelectionKey.OP_WRITE);
}
private void doWrite(SelectionKey key) throws IOException {
System.out.println("write data to server...");
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.wrap(new String("Hi, server").getBytes("UTF-8"));
while (buffer.hasRemaining()) {
channel.write(buffer);
}
channel.register(selector, SelectionKey.OP_READ);
}
public void stopServer() throws IOException {
if (selector != null && selector.isOpen()) {
selector.close();
}
}
public static void main(String[] args) throws IOException, InterruptedException {
NIOClient client = new NIOClient();
try {
client.initClient(8859);
client.start();
} catch (Exception e) {
client.stopServer();
}
}
}