-
服务端代码
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.util.Iterator;
public class NIOServer {
//服务所用端口
private static final int PORT=9999;
//选择器
private Selector selector;
//服务端serverSocketChannel, 主要功能是处理事件
private ServerSocketChannel serverSocketChannel;
//初始化服务端
{
try {
//创建选择器
selector=Selector.open();
//创建serverSocketChannel
serverSocketChannel=ServerSocketChannel.open();
//设置为非阻塞式
serverSocketChannel.configureBlocking(false);
//绑定端口
serverSocketChannel.socket().bind(new InetSocketAddress(PORT));
//把serverSocketChannel注册到选择器,使选择器监听accept事件
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
}catch (Exception e){
e.printStackTrace();
}
}
//事件监听:accept和read事件
public void listener(){
while (true) {
try {
System.out.println("开始监听事件");
//当没有事件发生时会阻塞在此位置,也可设置不阻塞或阻塞超时时间
selector.select();
//当有事件发生时,获取发生事件的SelectionKey集合,通过SelectionKey可以获取socketChannel通道和发生事件的类型等
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
System.out.print("监听到事件:");
SelectionKey selectionKey = iterator.next();
//accept事件处理
if (selectionKey.isAcceptable()) {
System.out.println("连接事件");
//使用serverSocketChannel分配一个代表客户端连接的socketChannel
SocketChannel socketChannel = serverSocketChannel.accept();
//设置为非阻塞式
socketChannel.configureBlocking(false);
//注册到选择器上,并让选择器监听read事件
socketChannel.register(selector, SelectionKey.OP_READ);
}
//read事件处理
if (selectionKey.isReadable()) {
System.out.println("消息读取事件");
//获取事件发生、代表客户端连接的socketChannel
SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
//读取通道的数据到缓存,用来记录日志
ByteBuffer b = ByteBuffer.allocate(1024);
int read = socketChannel.read(b);
String msg=new String(b.array(), 0, read);
String addr = socketChannel.getRemoteAddress().toString().substring(11)+"说:";
System.out.println("服务器群发消息:"+addr+msg);
//群发消息(不包含自己)
sendMsgToAll(selectionKey,msg);
}
//移出处理完事件的selectionKey
iterator.remove();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
//群发消息(不包含自己)
private void sendMsgToAll(SelectionKey self,String msg){
System.out.println("一共有"+selector.keys().size()+"个连接");
try {
SocketChannel socketChannel = (SocketChannel) self.channel();
String addr = socketChannel.getRemoteAddress().toString().substring(11)+"说:";
msg=addr+msg;
String finalMsg = msg;
selector.keys().stream().filter(selectionKey -> self!=selectionKey).forEach(selectionKey->{
try {
//群发消息(ServerSocketChannel除外)
if(selectionKey.channel() instanceof SocketChannel) {
//获取代表客户端连接的socketChannel通道
SocketChannel socketChannel1 = (SocketChannel) selectionKey.channel();
//把缓存内的数据写入到socketChannel通道
socketChannel1.write(ByteBuffer.wrap(finalMsg.getBytes()));
}
} catch (IOException e) {
e.printStackTrace();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
NIOServer server=new NIOServer();
server.listener();
}
}
-
客户端代码
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Scanner;
public class NIOClient {
// 客户端socketChannel
private SocketChannel socketChannel;
{
try {
//创建socketChannel
socketChannel=SocketChannel.open();
//设置非阻塞式
socketChannel.configureBlocking(false);
InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 9999);
// 创建连接
if(!socketChannel.connect(inetSocketAddress)){
while (!socketChannel.finishConnect()){
System.out.println("客户端不会阻塞,可以做其他工作");
}
}
//连接成功后开启一个线程定时2秒接收服务器转发的消息
receiveMsg();
} catch (IOException e) {
e.printStackTrace();
}
}
// 收消息线程
private void receiveMsg(){
new Thread(()->{
System.out.println("开始收取信息...");
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (true) {
try {
//把通道的数据写入缓存buffer
int read = socketChannel.read(buffer);
if(read>0)
System.out.println(new String(buffer.array(),0,read));
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}finally {
//清空缓存buffer
buffer.clear();
}
}
}).start();
}
//发送消息
public void sendMsg(String msg){
try {
//发送消息
socketChannel.write(ByteBuffer.wrap(msg.getBytes()));
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
NIOClient client=new NIOClient();
// 循环发送消息
Scanner scanner=new Scanner(System.in);
while (scanner.hasNextLine()) {
try {
client.sendMsg(scanner.nextLine());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}