Java NIO实现聊天系统

使用Java的NIO写的一个小的聊天系统,供大家参考,具体内容如下

一、服务端

/**

* 群聊的服端

*

* @author :breakpoint/赵立刚

* @date : 2020/08/13

*/

public class GroupChatServer {

// 定义相关的属性

private Selector selector;

private ServerSocketChannel listenChannel;

private static final int port = 6667;

// 构造器

// 进行初始化的操作

public GroupChatServer() {

try {

// 获取选择器

selector = Selector.open();

// 获取到 listenChannel

listenChannel = ServerSocketChannel.open();

// 设定端口

listenChannel.bind(new InetSocketAddress(port));

// 设定非阻塞模式

listenChannel.configureBlocking(false);

// 将该 listenChannel 注册到 selector上 完成操作

listenChannel.register(selector, SelectionKey.OP_ACCEPT);

System.out.println("服务器启动了。。。。");

} catch (IOException e) {

}

}

// 监听的代码

public void listen() {

try {

// 循环处理

while (true) {

int count = selector.select(2000);

if (count > 0) {

// 有事件需要处理

// 遍历处理 得到selectionKeys集合

Set<SelectionKey> selectionKeys = selector.selectedKeys();

Iterator<SelectionKey> selectionKeyIterator = selectionKeys.iterator();

while (selectionKeyIterator.hasNext()) {

// 得到selectionKey

SelectionKey selectionKey = selectionKeyIterator.next();

// 监听到了 accept

if (selectionKey.isAcceptable()) {

// 获取到连接

SocketChannel sc = listenChannel.accept();

sc.configureBlocking(false);

sc.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));

// 提示上线

System.out.println(sc.getRemoteAddress() + ":上线啦。。。。");

}

if (selectionKey.isReadable()) {

// 读取事件 通道是可以读的状态 //专门写

readData(selectionKey);

}

// 移除当前的删除 防止重复处理操作

selectionKeyIterator.remove();

}

} else {

System.out.println("等待中。。。。。。");

}

}

} catch (Exception e) {

} finally {

}

}

// 读取客户端的消息

private void readData(SelectionKey selectionKey) {

// 获取 socketChannel

SocketChannel channel = null;

try {

channel = (SocketChannel) selectionKey.channel();

ByteBuffer byteBuffer = (ByteBuffer) selectionKey.attachment();

int count = channel.read(byteBuffer);

// 分情况处理

if (count > 0) {

// 获取到数据专程

String msg = new String(byteBuffer.array(), 0, count);

byteBuffer.clear();

System.out.println(channel.getRemoteAddress() + "来自客户端" + msg);

// 向其他的客户端转发消息

sendInfoToOtherClients(msg, channel);

}

} catch (IOException e) {

// 如果发生异常 提示说明离线了

try {

System.out.println(channel.getRemoteAddress() + "离线了。。。。");

// 取消注册

selectionKey.cancel();

// 关闭通道

channel.close();

} catch (IOException e1) {

//e1.printStackTrace();

}

} finally {

}

}

// 转发消息给其他的客户端 去掉自己的客户端

private void sendInfoToOtherClients(String msg, SocketChannel self) throws IOException {

System.out.println("服务器转发消息。。。。。");

// 进行遍历操作

Set<SelectionKey> keys = selector.keys();

for (SelectionKey key : keys) {

// 取出来所有的

Channel targetChannel = key.channel();

// 排除自己

if (targetChannel instanceof SocketChannel && targetChannel != self) {

SocketChannel dest = (SocketChannel) targetChannel;

ByteBuffer byteBuffer = ByteBuffer.wrap(msg.getBytes());

// 发送数据

dest.write(byteBuffer);

}

}

}

public static void main(String[] args) {

GroupChatServer groupChatServer = new GroupChatServer();

groupChatServer.listen();

}

}

二、客户端代码

/**

* @author :breakpoint/赵立刚

* @date : 2020/08/13

*/

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() {

try {

selector = Selector.open();

// 连接服务器

socketChannel = SocketChannel.open(new InetSocketAddress(HOST, port));

// 设置非阻塞工作

socketChannel.configureBlocking(false);

// 注册我们的通道

socketChannel.register(selector, SelectionKey.OP_READ);

userName = socketChannel.getLocalAddress().toString();

System.out.println("客户端专备好啦");

} catch (IOException e) {

}

}

public void sendInfo(String info) {

String msg = userName + "说:" + info;

try {

ByteBuffer wrap = ByteBuffer.wrap(msg.getBytes());

socketChannel.write(wrap);

} catch (IOException e) {

e.printStackTrace();

}

}

// 读取信息

public void readInfo() {

try {

int readChannel = selector.select(2000);

if (readChannel > 0) {

// 有可以用的通道

Set<SelectionKey> selectionKeys = selector.selectedKeys();

Iterator<SelectionKey> iterator = selectionKeys.iterator();

while (iterator.hasNext()) {

SelectionKey next = iterator.next();

if (next.isReadable()) {

SelectableChannel keyChannel = next.channel();

if (keyChannel instanceof SocketChannel) {

// 获取到我们的通道

SocketChannel channel = (SocketChannel) keyChannel;

ByteBuffer allocate = ByteBuffer.allocate(1024);

// 读取数据

int read = channel.read(allocate);

if (read > 0) {

// 输出我们的消息

System.out.println(new String(allocate.array(), 0, read));

}

}// end if

}

iterator.remove();

}

} else {

System.out.println("没有可用的通道");

}

} catch (IOException e) {

}

}

public static void main(String[] args) throws Exception {

// 启动客户端的操作

final GroupChatClient groupChatClient = new GroupChatClient();

// 启动一个线程

new Thread(() -> {

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);

}

System.in.read();

}

}

三、运行的结果

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。 

以上是 Java NIO实现聊天系统 的全部内容, 来源链接: utcz.com/p/250992.html

回到顶部