功能说明:
- 编写NIO群聊系统。实现服务器端和客户端的数据简单通信
- 实现多人群聊
- 服务器端:可以检测用户上限,离线,并实现消息转发功能
- 客户端:通过channel可以无阻塞的发消息给用户,同时可以接受其他用户发送的消息
服务器端:
private Selector selector;
private static final int PORT = 6667;
//构造器 初始化
public ChatServer() {
try {
selector = Selector.open();
listenChannel = ServerSocketChannel.open();
//绑定端口
listenChannel.socket().bind(new InetSocketAddress(PORT));
//设置非阻塞
listenChannel.configureBlocking(false);
//注册到selector
listenChannel.register(selector, SelectionKey.OP_ACCEPT);
} catch (Exception e) {
e.getStackTrace();
}
}
//监听
private void listen() {
try {
//循环处理
while (true) {
int count = selector.select();
if (count > 0) { //有事件处理
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
if (key.isAcceptable()) {
SocketChannel socketChannel = listenChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
//提示
System.out.println(socketChannel.getRemoteAddress() + "上线");
}
if (key.isReadable()) {
//处理读
readData(key);
}
iterator.remove();
}
}
}
} catch (Exception e) {
e.getStackTrace();
}
}
//读取客户端消息
private void readData(SelectionKey key) {
try {
//得到通道 创建buffer
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
int read = channel.read(byteBuffer);
if(read>0){
String s = new String(byteBuffer.array());
//输出消息
System.out.println("form 客户端"+s);
//向其他的客户端转发消息(除了自己)
sendDataToOther(s,channel);
}
} catch (Exception e) {
e.getStackTrace();
}
}
private void sendDataToOther(String s,SocketChannel socketChannel) throws IOException {
System.out.println("服务器转发消息中");
//遍历 所有注册到selector上的socketchannel 并排除自己
for (SelectionKey key : selector.keys()) {
//通过key 取得对应的socketchannel
SocketChannel channel = (SocketChannel)key.channel();
//排除自己
if(channel instanceof SocketChannel && channel!=socketChannel){
//将 消息 存储到buffer
ByteBuffer byteBuffer = ByteBuffer.wrap(s.getBytes());
//将buffer写入通道
channel.write(byteBuffer);
}
}
}
public static void main(String[] args) {
//创建服务器对象
ChatServer chatServer = new ChatServer();
chatServer.listen();
}
客户端:
//启动客户端
ChatClient chatClient=new ChatClient();
new Thread(){
@Override
public void run() {
while (true){
try {
chatClient.readData();
Thread.sleep(3000);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}.start();
//发送数据到 服务端
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()){
String s = scanner.nextLine();
chatClient.sendData(s);
}
}
//定义相关属性
private final String HOST = "127.0.0.1";
private final int PORT = 6667;
private Selector selector;
private SocketChannel socketChannel;
private String userName;
//构造器 完成初始化工作
public ChatClient() throws Exception {
selector = Selector.open();
//连接 服务器
socketChannel = SocketChannel.open(new InetSocketAddress(HOST, PORT));
//设置非阻塞
socketChannel.configureBlocking(false);
//将channel 注册到 selector
socketChannel.register(selector, SelectionKey.OP_READ);
//得到userName
userName = socketChannel.getLocalAddress().toString().substring(1);
System.out.println(userName + " is ok..........");
}
public void sendData(String info) {
try {
info = userName + "说:" + info;
socketChannel.write(ByteBuffer.wrap(info.getBytes()));
} catch (Exception e) {
e.getStackTrace();
}
}
public void readData() throws IOException {
int count = selector.select();
if (count > 0) {
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
if (key.isReadable()) {
//得到通道
SocketChannel channel = (SocketChannel) key.channel();
//得到一个buffer
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//读取
channel.read(byteBuffer);
//把读到的缓冲区里面的数据 转成字符串
String s = new String(byteBuffer.array());
System.out.println(s.trim());
}
}
iterator.remove();
}
}