首先,創建服務端類,代碼如下
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.util.Iterator;
/**
* 測試一個線程監聽兩個socket的類
* @author andy
*
*/
public class ServerDemo implements Runnable{
private int port1 = 8099;//端口
private int port2 = 8088;
private ServerSocketChannel serversocketchannel1;//服務器通道
private ServerSocketChannel serversocketchannel2;
private SocketChannel socketChannel1;//連接
private SocketChannel socketChannel2;
private Selector selector;//選擇器
private ByteBuffer byteBuffer = ByteBuffer.allocate(512);//緩衝區
public ServerDemo() {
init();
}
@Override
public void run() {
while(true) {
try{
System.out.println("thread is runing ……");
selector.select();
Iterator selectorkeys = selector.selectedKeys().iterator();
while(selectorkeys.hasNext()) {
SelectionKey key = (SelectionKey) selectorkeys.next();
selectorkeys.remove();
if(!key.isValid()) {
continue;
}
if(key.isAcceptable()) {
accept(key);
} else if(key.isReadable()) {
read(key);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 初始化測試類
* 1.初始化選擇器
* 2.打開兩個通道
* 3.給通道上綁定一個socket
* 4.將選擇器註冊到通道上
*/
public void init() {
try{
selector = SelectorProvider.provider().openSelector();//創建選擇器
//初始化第一個服務端
serversocketchannel1 = ServerSocketChannel.open();//打開第一個通道
serversocketchannel1.configureBlocking(false);//設置非阻塞方式
serversocketchannel1.socket().bind(new InetSocketAddress("localhost",port1));
serversocketchannel1.register(selector, SelectionKey.OP_ACCEPT);
//初始化第二個服務端
serversocketchannel2 = ServerSocketChannel.open();
serversocketchannel2.configureBlocking(false);
serversocketchannel2.socket().bind(new InetSocketAddress("localhost",port2));
serversocketchannel2.register(selector, SelectionKey.OP_ACCEPT);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 客戶端連接服務器
* @param key
*/
public void accept(SelectionKey key) {
ServerSocketChannel channel = (ServerSocketChannel) key.channel();
try{
if(channel.equals(serversocketchannel1)) {
socketChannel1 = channel.accept();
socketChannel1.configureBlocking(false);
socketChannel1.register(selector, SelectionKey.OP_READ);
} else {
socketChannel2 = channel.accept();
socketChannel2.configureBlocking(false);
socketChannel2.register(selector, SelectionKey.OP_READ);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 從通道中讀取數據
* @param key
*/
public void read(SelectionKey key) {
this.byteBuffer.clear();//清空緩存
SocketChannel channel = (SocketChannel) key.channel();
try {
int count = channel.read(byteBuffer);
if(count == -1) {
key.channel().close();
key.cancel();
return;
}
//從緩衝區中取數據
String input = new String(byteBuffer.array()).trim();
if(channel.equals(socketChannel1)) {
System.out.println("歡迎使用服務器1!");
System.out.println("信息:" + input);
} else {
System.out.println("歡迎使用服務器2!");
System.out.println("信息:" + input);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ServerDemo serverDemo = new ServerDemo();
Thread thread = new Thread(serverDemo);
thread.start();
}
}
再創建客戶端類,代碼如下:
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
public class ClientDemo {
private ByteBuffer buffer = ByteBuffer.allocate(512);//創建一個緩衝區
public void query(String host,int port) {
try {
InetSocketAddress address = new InetSocketAddress(InetAddress.getByName(host), port);
SocketChannel channel = null;
byte[] bytes = new byte[512];
while(true) {
try{
System.in.read(bytes);
channel = SocketChannel.open();
channel.connect(address);
buffer.clear();
buffer.put(bytes);
buffer.flip();
channel.write(buffer);
buffer.clear();
} catch(Exception e ) {
e.printStackTrace();
} finally {
if(channel != null) {
try {
channel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new ClientDemo().query("localhost", 8099);
new ClientDemo().query("localhost", 8088);
}
}
測試的時候,首先運行服務端類,再運行客戶端類。
在客戶端控制檯上可以直接輸入內容 按回車鍵之後,切換到服務端的控制檯。就能收到服務端打印出來的消息