服务端
public void startServer() throws Exception {
Selector sel = Selector.open();
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.bind(new InetSocketAddress(8000));
ssc.configureBlocking(false);
ssc.register(sel, SelectionKey.OP_ACCEPT);
System.out.println("server starting...");
for (;;) {
int channelCount = sel.select();
if (channelCount == 0) continue;
Set<SelectionKey> sks = sel.selectedKeys();
Iterator<SelectionKey> it = sks.iterator();
while(it.hasNext()) {
SelectionKey sk = it.next();
it.remove();
if (sk.isAcceptable()) {
acceptOperator(ssc, sel);
} else if (sk.isReadable()) {
readOperator(sel, sk);
}
}
}
}
private void acceptOperator(ServerSocketChannel ssc, Selector sel) throws Exception {
SocketChannel sc = ssc.accept();
sc.configureBlocking(false);
sc.register(sel, SelectionKey.OP_READ);
sc.write(Charset.forName("UTF-8").encode("欢迎进入聊天室,请注意隐私安全"));
}
private void readOperator(Selector sel, SelectionKey sk) throws Exception {
SocketChannel sc = (SocketChannel) sk.channel();
ByteBuffer bb = ByteBuffer.allocate(1024);
int len = sc.read(bb);
String message = "";
if (len > 0) {
bb.flip();
message += Charset.forName("UTF-8").decode(bb);
}
sc.register(sel, SelectionKey.OP_READ);
if (message.length() > 0) {
System.out.println(sc + " - " + message);
castOtherClient(message, sel, sc);
}
}
private void castOtherClient(String message, Selector sel, SocketChannel sc) throws Exception {
Set<SelectionKey> sks = sel.keys();
for (SelectionKey sk : sks) {
SelectableChannel otherSC = sk.channel();
if (otherSC instanceof SocketChannel && otherSC != sc) {
((SocketChannel) otherSC).write(Charset.forName("UTF-8").encode(message));
}
}
}
客户端
public void startClient(String name) throws Exception {
SocketChannel sc = SocketChannel.open(new InetSocketAddress("localhost", 8000));
Scanner scanner = new Scanner(System.in);
Selector sel = Selector.open();
sc.configureBlocking(false);
sc.register(sel, SelectionKey.OP_READ);
new Thread(new ClientThread(sel)).start();
while (scanner.hasNextLine()) {
String msg = scanner.nextLine();
if (msg.length() > 0) {
sc.write(Charset.forName("UTF-8").encode(name + " - " + msg));
}
}
}
public class ClientThread implements Runnable{
private Selector sel
public ClientThread(Selector sel) {
this.sel = sel
}
@Override
public void run() {
try {
for (
int channelCount = sel.select()
if (channelCount == 0) continue
//获取可用的channel
Set<SelectionKey> sks = sel.selectedKeys()
Iterator<SelectionKey> it = sks.iterator()
while(it.hasNext()) {
//获取一个
SelectionKey sk = it.next()
//移除
it.remove()
//只关注可读状态
if (sk.isReadable()) {
//可读状态
readOperator(sel, sk)
}
}
}
} catch (Exception e) {
}
}
private void readOperator(Selector sel, SelectionKey sk) throws Exception {
//获取channel
SocketChannel sc = (SocketChannel) sk.channel()
ByteBuffer bb = ByteBuffer.allocate(1024)
int len = sc.read(bb)
String message = ""
if (len > 0) {
bb.flip()
//读取
message += Charset.forName("UTF-8").decode(bb)
}
//再次注册这个channel,监听后后面的可读信息
sc.register(sel, SelectionKey.OP_READ)
if (message.length() > 0) {
System.out.println(sc + " - " + message)
}
}
}
另一个版本
服务端
public class GroupChatServer {
private Selector sel;
private ServerSocketChannel ssc;
private final static int PORT = 7777;
public GroupChatServer() {
try {
sel = Selector.open();
ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(PORT));
ssc.configureBlocking(false);
ssc.register(sel, SelectionKey.OP_ACCEPT);
} catch (IOException e) {
e.printStackTrace();
}
}
public void listen() {
try {
while (true) {
int count = sel.select();
if (count > 0) {
Iterator<SelectionKey> keyIterator = sel.selectedKeys().iterator();
while (keyIterator.hasNext()) {
SelectionKey sk = keyIterator.next();
if (sk.isAcceptable()) {
SocketChannel sc = ssc.accept();
sc.configureBlocking(false);
sc.register(sel, SelectionKey.OP_READ);
System.out.println(sc.getRemoteAddress().toString().substring(1) + " - 上线");
} else if (sk.isReadable()) {
readData(sk);
}
keyIterator.remove();
}
} else {
System.out.println("wait...");
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
private void readData(SelectionKey sk) {
SocketChannel sc = null;
try {
sc = (SocketChannel) sk.channel();
ByteBuffer bb = ByteBuffer.allocate(1024);
int len = sc.read(bb);
if (len > 0) {
String msg = new String(bb.array(), 0, len);
System.out.println("from client: " + msg);
sendInfoToOtherClients(msg, sc);
}
} catch (IOException e) {
try {
System.out.println(sc.getRemoteAddress().toString().substring(1) + " - 离线");
sk.cancel();
sc.close();
} catch (IOException ex) {
ex.printStackTrace();
}
} finally {
}
}
private void sendInfoToOtherClients(String msg, SocketChannel sc) throws IOException {
System.out.println("群发消息...");
for (SelectionKey key : sel.keys()) {
Channel toSc = key.channel();
if (toSc instanceof SocketChannel && toSc != sc) {
ByteBuffer bb = ByteBuffer.wrap(msg.getBytes());
((SocketChannel) toSc).write(bb);
}
}
}
public static void main(String[] args) {
GroupChatServer gcs = new GroupChatServer();
gcs.listen();
}
}
客户端
public class GroupChatClient {
private final static String HOST = "127.0.0.1"
private final static int PORT = 7777
private Selector sel
private SocketChannel sc
private String username
public GroupChatClient() {
try {
sel = Selector.open()
sc = SocketChannel.open(new InetSocketAddress(HOST, PORT))
sc.configureBlocking(false)
sc.register(sel, SelectionKey.OP_READ)
username = sc.getLocalAddress().toString().substring(1)
System.out.println(username + " - ready")
} catch (IOException e) {
e.printStackTrace()
}
}
//发送信息
public void sendInfo (String info) {
info = username + " - " + info
try {
sc.write(ByteBuffer.wrap(info.getBytes()))
} catch (IOException e) {
e.printStackTrace()
}
}
//读取其他通道转发来的信息
public void readInfo() {
while (true) {
try {
int readChannels = sel.select()
if (readChannels > 0) {
Iterator<SelectionKey> keyIterator = sel.selectedKeys().iterator()
while (keyIterator.hasNext()) {
SelectionKey sk = keyIterator.next()
if (sk.isReadable()) {
SocketChannel sc = (SocketChannel) sk.channel()
ByteBuffer bb = ByteBuffer.allocate(1024)
int len = sc.read(bb)
if (len > 0) {
String msg = new String(bb.array(), 0, len)
System.out.println(username + " receive: " + msg)
}
}
keyIterator.remove()
}
}
} catch (IOException e) {
e.printStackTrace()
}
}
}
public static void main(String[] args) {
//启动
GroupChatClient gcc = new GroupChatClient()
//每个三秒读取数据
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
gcc.readInfo()
}
}
}).start()
//发送数据
Scanner scanner = new Scanner(System.in)
while(scanner.hasNextLine()) {
String s = scanner.nextLine()
gcc.sendInfo(s)
}
}
}