Java NIO群聊系统Demo
使用的是NIO三大组件,前面介绍的知识。
服务端编写
(1)服务器启动并接听6667
(2)监听上线和下线
(3)接收客户端消息,并实现转发
package NIO.chat;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;
public class Server {
//定义属性
private Selector selector;
private ServerSocketChannel serverSocketChannel;
private static final int PORT = 6667;
//构造器
public Server(){
try {
//获取选择器和服务器端channel
selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
//绑定端口
serverSocketChannel.bind(new InetSocketAddress(PORT));
//设置非阻塞模式
serverSocketChannel.configureBlocking(false);
//将channel注册到selector中
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
} catch (IOException e) {
e.printStackTrace();
}
}
//监听程序
public void listen(){
try {
while(true){
int count = selector.select();
if (count>0) {
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()){
SelectionKey key = iterator.next();
//监听到连接事件
if (key.isAcceptable()){
SocketChannel accept = serverSocketChannel.accept();
accept.configureBlocking(false);
//将该channel注册到选择器中,监听可读事件
accept.register(selector,SelectionKey.OP_READ);
System.out.println(accept.getRemoteAddress()+" 上线了");
}
//监听到通道可读
if (key.isReadable()) {
//处理读
readData(key);
}
//删除key,防止重复操作
iterator.remove();
}
} else {
System.out.println("等待连接。。。");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
//读取客户端消息
public void readData(SelectionKey key){
SocketChannel channel = null;
try {
channel = (SocketChannel) key.channel();
//创建buffer
ByteBuffer buffer = ByteBuffer.allocate(1024);
int count = channel.read(buffer);
if(count>0){
//把缓冲区的数据转换成字符串
String msg = new String(buffer.array());
System.out.println("from 客户端"+ channel.getRemoteAddress() + ":"+ msg);
//向其他客户端转发消息,排除自己。
sendMSGToOtherClient(msg,channel);
}
} catch (IOException e) {
try {
System.out.println(channel.getRemoteAddress() + "下线了");
//取消注册
key.cancel();
//关闭通道
channel.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
public void sendMSGToOtherClient(String msg, SocketChannel self) throws IOException {
//遍历所有注册到selector上的channel。
for (SelectionKey key : selector.keys()){
Channel target = key.channel();
if (target instanceof SocketChannel && target != self){
SocketChannel socketChannel = (SocketChannel) target;
//转发信息
ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
socketChannel.write(buffer);
}
}
}
public static void main(String[] args) {
//创建服务器端对象
Server server = new Server();
server.listen();
}
}
客户端编写
(1)连接服务器
(2)发送消息
(3)接受消息
package NIO.chat;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;
public class Client {
//服务器相关信息
private final String HOST = "127.0.0.1";
private final int PORT = 6667;
private Selector selector;
private SocketChannel socketChannel;
private String username;
public Client() throws IOException {
selector = Selector.open();
socketChannel = SocketChannel.open(new InetSocketAddress(HOST,PORT));
//设置非阻塞
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
//得到username
username = socketChannel.getLocalAddress().toString();
System.out.println(username + "is ok");
}
//向服务器发送消息
public void sendMSG(String msg) throws IOException {
msg = username + " 说:" + msg;
socketChannel.write(ByteBuffer.wrap(msg.getBytes()));
}
//读取服务端消息
public void readMSG() throws IOException {
int readChannels = selector.select();
if(readChannels>0){
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()){
SelectionKey key = iterator.next();
//监听到通道可读
if (key.isReadable()) {
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer);
String msg = new String(buffer.array());
System.out.println(msg);
}
//删除key,防止重复操作
iterator.remove();
}
} else {
System.out.println("没有可用通道");
}
}
public static void main(String[] args) throws IOException {
//启动客户端
Client client = new Client();
//启动一个线程监听服务端发送的数据
new Thread(){
public void run(){
while (true){
try {
client.readMSG();
//每隔3秒从服务器端读取数据
Thread.currentThread().sleep(3000);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
//发送数据
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()){
String s = scanner.nextLine();
client.sendMSG(s);
}
}
}