服务端:
package com.jym.nio.groupChat;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;
/**
* @program: JymNetty
* @description: 服务端
* @author: jym
* @create: 2020/02/02
*/
public class GroupChatServer {
private Selector selector;
private ServerSocketChannel serverSocketChannel;
private final int PORT=6667;
/**
* 通过构造方法来初始化各个参数
*/
public GroupChatServer() {
try {
selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.socket().bind(new InetSocketAddress(PORT));
serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @description:主要监听方法
*/
public void listen(){
try {
while (true){
int select = selector.select();
if(select>0){
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()){
SelectionKey selectionKey = iterator.next();
if(selectionKey.isAcceptable()){
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector,SelectionKey.OP_READ);
System.out.println(socketChannel.getRemoteAddress()+"上线了");
}
if(selectionKey.isReadable()){
readData(selectionKey);
}
iterator.remove();
}
}else {
System.out.println("系统正在等待人上线....");
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
/**
* @description:读取客户端发送的消息,并向其他客户端转发消息
* @param selectionKey
*/
private void readData(SelectionKey selectionKey){
SocketChannel socketChannel = null;
try {
socketChannel = (SocketChannel)selectionKey.channel();
socketChannel.configureBlocking(false);
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
int read = socketChannel.read(byteBuffer);
if(read>0){
String msg = new String(byteBuffer.array());
System.out.println("from客户端"+msg);
// 向其他客户端转发消息
sendInfoToOtherClient(msg,socketChannel);
}
} catch (IOException e) {
try {
System.out.println(socketChannel.getRemoteAddress()+"离线了");
// 取消注册
selectionKey.cancel();
socketChannel.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
/**
* @description: 向其他客户端转发消息
* @param msg
* @param socketChannel
*/
private void sendInfoToOtherClient(String msg, SocketChannel socketChannel){
System.out.println("服务器转发消息中");
// 遍历所有注册到selector的所有channel,排除自己
for (SelectionKey selectionKey : selector.keys()) {
Channel taGetChannel = selectionKey.channel();
if(taGetChannel instanceof SocketChannel && taGetChannel!=socketChannel){
SocketChannel socketChannel1 = (SocketChannel)taGetChannel;
ByteBuffer byteBuffer = ByteBuffer.wrap(msg.getBytes());
try {
socketChannel1.write(byteBuffer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
GroupChatServer groupChatServer = new GroupChatServer();
groupChatServer.listen();
}
}
服务端:
package com.jym.nio.groupChat;
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.SocketChannel;
import java.util.Iterator;
import java.util.Scanner;
/**
* @program: JymNetty
* @description: 客户端
* @author: jym
* @create: 2020/02/02
*/
public class GroupChatClient {
private final String HOST = "127.0.0.1";
private final int PORT = 6667;
private Selector selector;
private SocketChannel socketChannel;
private String username;
public GroupChatClient() throws IOException {
selector = Selector.open();
// 连接服务器
socketChannel = SocketChannel.open(new InetSocketAddress(HOST, PORT));
this.socketChannel.configureBlocking(false);
this.socketChannel.register(selector, SelectionKey.OP_READ);
username = this.socketChannel.getRemoteAddress().toString().substring(1);
System.out.println(username+"isOK");
}
/**
* @description: 发送消息
* @param info
*/
public void sendInfo(String info){
info = username+"说:" + info;
try {
socketChannel.write(ByteBuffer.wrap(info.getBytes()));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 读取消息
*/
public void readInfo(){
try {
int read = selector.select();
if(read>0){
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()){
SelectionKey selectionKey = iterator.next();
if(selectionKey.isReadable()){
SocketChannel channel = (SocketChannel)selectionKey.channel();
channel.configureBlocking(false);
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
int read1 = channel.read(byteBuffer);
if(read1>0){
System.out.println(new String(byteBuffer.array()).trim());
}
}
iterator.remove();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
// 启动客户端
GroupChatClient groupChatClient = new GroupChatClient();
// 启动一个线程,没隔三秒,读取发送的数据
new Thread(new Runnable() {
@Override
public void run() {
while (true){
groupChatClient.readInfo();
try {
Thread.currentThread().sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
// 发送数据
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()){
String s = scanner.nextLine();
groupChatClient.sendInfo(s);
}
}
}
我们用idea 启动·两个客户端一个服务端:
结果:
服务端
客户端1:
客户端2:
这里说一下idea启动两个mian的方法:
点击加号,选择application
输入class名称然后确定
然后选择我们新建的application,点击运行按钮即可