首先,创建服务端类,代码如下
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);
}
}
测试的时候,首先运行服务端类,再运行客户端类。
在客户端控制台上可以直接输入内容 按回车键之后,切换到服务端的控制台。就能收到服务端打印出来的消息