java中nio怎么实现聊天,JAVA-NIO实现聊天室详细代码说明

JAVA-NIO实现聊天室详细代码说明

JAVA-NIO实现聊天室详细代码说明

github源码:https://github.com/JolyouLu/JAVAIO.git

src\main\java\com\JolyouLu\nio\groupchat 文件夹下

public class GroupChatServer {

//定义属性

private Selector selector;

private ServerSocketChannel listenChannel;

private static final int PORT = 6666;

//构造器 完成初始化工作

public GroupChatServer() {

try {

//得到选择器

selector = Selector.open();

//初始化ServerSocketChannel

listenChannel = ServerSocketChannel.open();

//绑定端口

listenChannel.socket().bind(new InetSocketAddress(PORT));

//设置非阻塞模式

listenChannel.configureBlocking(false);

//将来listenChannel注册到Selector

listenChannel.register(selector, SelectionKey.OP_ACCEPT);

}catch (IOException e){

e.printStackTrace();

}

}

//监听

public void listen(){

try {

//循环监听

while (true){

int count = selector.select(2000); //阻塞2秒监听,通道有没有事件发生

if (count > 0){ //返回>0 有事件要处理

//遍历selectedKeys集合

Iterator iterator = selector.selectedKeys().iterator();

while (iterator.hasNext()){

//获取SelectionKey

SelectionKey key = iterator.next();

if (key.isAcceptable()){ //如果通道发生,客户端连接事件

//为连接的客户端,生成socketChannel

SocketChannel socketChannel = listenChannel.accept();

//切换非阻塞模式

socketChannel.configureBlocking(false);

//把socketChannel注册到selector中,并监听读事件

socketChannel.register(selector,SelectionKey.OP_READ);

//提示客户端连接上了

System.out.println(socketChannel.getRemoteAddress() + " 客户端 上线");

}

if (key.isReadable()){//如果通道发生,可读事件

//处理读

readData(key);

}

//清理读取的selectedKeys容器 防止重复处理

iterator.remove();

}

}

}

}catch (Exception e){

e.printStackTrace();

}finally {

}

}

//读取客户端消息

private void readData(SelectionKey key){

//定义一个SocketChannel

SocketChannel channel = null;

try {

//取到关联的channel

channel = (SocketChannel) key.channel();

//创建buffer

ByteBuffer buffer = ByteBuffer.allocate(1024);

int count = channel.read(buffer);

//根据count的值做处理

if (count > 0){ //读取到数据

//把缓冲区的数据转字符串

String msg = new String(buffer.array(), "GBK");

//输出消息

System.out.println("from 客户端:"+ msg);

//向其它客户端转发消息

sendInfoToOtherClients(msg,channel);

}

}catch (IOException e){

try {

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

//取消注册

key.cancel();

//关闭通道

channel.close();

} catch (IOException ioException) {

ioException.printStackTrace();

}

}

}

//转发消息给其它客户端(channel)

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

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

//遍历 所有的注册到Selector的SocketChannel排查self

for (SelectionKey key : selector.keys()) {

//取出通道

Channel targetChannel = key.channel();

//targetChanneld的类型是SocketChannel,并且targetChannel不是自己

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

//转型

SocketChannel dest = (SocketChannel)targetChannel;

//将来msg 存到buffer

ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes("GBK"));

//将来buffer的数据写入通道

dest.write(buffer);

}

}

}

public static void main(String[] args) {

//初始化服务器对象

GroupChatServer chatServer = new GroupChatServer();

chatServer.listen();

}

}

客户端

public class GroupChatClient {

//定义相关属性

private final String HOST = "127.0.0.1"; //服务器IP

private final int PORT = 6666; //服务器端口

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注册到Selector,关注读事件

socketChannel.register(selector, SelectionKey.OP_READ);

//得到username

username = socketChannel.getLocalAddress().toString().substring(1);

System.out.println(username + " is ok ...");

}catch (Exception e){

e.printStackTrace();

}

}

//向服务器发送消息

public void sendInfo(String info){

info = username + " 说:" + info;

try {

socketChannel.write(ByteBuffer.wrap(info.getBytes("GBK")));

}catch (IOException e){

e.printStackTrace();

}

}

//读取从服务器端回复的消息

public void readInfo(){

try {

int readChannels = selector.select(2000);

if (readChannels > 0){//有可用的通道

Iterator iterator = selector.selectedKeys().iterator();

while (iterator.hasNext()){

SelectionKey key = iterator.next();

if (key.isReadable()){

//得到相关的通道

SocketChannel socketChannel = (SocketChannel) key.channel();

//得到一个Buffer

ByteBuffer buffer = ByteBuffer.allocate(1024);

//buffer 读取通道数据

socketChannel.read(buffer);

//把读到缓冲区的数据转成字符串

String msg = new String(buffer.array());

System.out.println(msg.trim());

}

iterator.remove();

}

}

}catch (IOException e){

e.printStackTrace();

}

}

public static void main(String[] args) {

//启动客户端

GroupChatClient chatClient = new GroupChatClient();

//启动一个线程,每隔开3秒读取服务器发送的数据

new Thread(new Runnable() {

@Override

public void run() {

while (true){

chatClient.readInfo();

try {

Thread.currentThread().sleep(3000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}).start();

//发送数据

Scanner scanner = new Scanner(System.in);

while (scanner.hasNextLine()){

String s = scanner.nextLine();

chatClient.sendInfo(s);

}

}

}

测试

设置启动参数,当前类可以同时运行多个

05af2d7303337818dbb34eb38cd0e9b5.png

b6decadda5ecef207db3ea7f980ad314.png

0b930c45c4929fbb85178188be0a1fd4.png

8d7bda5fb2adee12101e0c19ea59aae8.png

JAVA-NIO实现聊天室详细代码说明相关教程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值