Java NIO实现聊天系统
短信预约 -IT技能 免费直播动态提醒
使用Java的NIO写的一个小的聊天系统,供大家参考,具体内容如下
一、服务端
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();
}
}
二、客户端代码
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();
}
}
三、运行的结果
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341