Java NIO实战之多人聊天室

网友投稿 222 2022-09-13


Java NIO实战之多人聊天室

本文实例为大家分享了java NIO实战之多人聊天室的具体代码,供大家参考,具体内容如下

NIO服务端

public class NioServer {

/**

* 启动

*/

public void start() throws IOException {

/**

* 1. 创建Selector

*/

Selector selector = Selector.open();

/**

* 2. 通过ServerSocketChannel创建channel通道

*/

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

/**

* 3. 为channel通道绑定监听端口

*/

serverSocketChannel.bind(new InetSocketAddress(8000));

/**

* 4. **设置channel为非阻塞模式**

*/

serverSocketChannel.configureBlocking(false);

/**

* 5. 将channel注册到selector上,监听连接事件

*/

serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

System.out.println("服务器启动成功!");

/**

* 6. 循环等待新接入的连接

*/

for (;;) { // while(true) c for;;

/**

* TODO 获取可用channel数量

*/

int readyChannels = selector.select();

/**

* TODO 为什么要这样!!?

*/

if (readyChannels == 0) continue;

/**

* 获取可用channel的集合

*/

Set selectionKeys = selector.selectedKeys();

Iterator iterator = selectionKeys.iterator();

while (iterator.hasNext()) {

/**

* selectionKey实例

*/

SelectionKey selectionKey = (SelectionKey) iterator.next();

/**

* **移除Set中的当前selectionKey**

*/

iterator.remove();

/**

* 7. 根据就绪状态,调用对应方法处理业务逻辑

*/

/**

* 如果是 接入事件

*/

if (selectionKey.isAcceptable()) {

acceptHandler(serverSocketChannel, selector);

}

/**

* 如果是 可读事件

*/

if (selectionKey.isReadable()) {

readHandler(selectionKey, selector);

}

}

}

}

/**

* 接入事件处理器

*/

private void acceptHandler(ServerSocketChannel serverSocketChannel,

Selector selector)

throws IOException {

/**

* 如果要是接入事件,创建socketChannel

*/

SocketChannel socketChannel = serverSocketChannel.accept();

/**

* 将socketChannel设置为非阻塞工作模式

*/

socketChannel.configureBlocking(false);

/**

* 将channel注册到selector上,监听 可读事件

*/

socketChannel.register(selector, SelectionKey.OP_READ);

/**

* 回复客户端提示信息

*/

socketChannel.write(Charset.forName("UTF-8")

.encode("你与聊天室里其他人都不是朋友关系,请注意隐私安全"));

}

/**

* 可读事件处理器

*/

private void readHandler(SelectionKey selectionKey, Selector selector)

throws IOException {

/**

* 要从 selectionKey 中获取到已经就绪的channel

*/

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

/**

* 创建buffer

*/

ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

/**

* 循环读取客户端请求信息

*/

String request = "";

while (socketChannel.read(byteBuffer) > 0) {

/**

* 切换buffer为读模式

*/

byteBuffer.flip();

/**

* 读取buffer中的内容

*/

request += Charset.forName("UTF-8").decode(byteBuffer);

}

/**

* 将channel再次注册到selector上,监听他的可读事件

*/

socketChannel.register(selector, SelectionKey.OP_READ);

/**

* 将客户端发送的请求信息 广播给其他客户端

*/

if (request.length() > 0) {

// 广播给其他客户端

broadCast(selector, socketChannel, request);

}

}

/**

* 广播给其他客户端

*/

private void broadCast(Selector selector,

SocketChannel sourceChannel, String request) {

/**

* 获取到所有已接入的客户端channel

*/

Set selectionKeySet = selector.keys();

/**

* 循环向所有channel广播信息

*/

selectionKeySet.forEach(selectionKey -> {

Channel targetChannel = selectionKey.channel();

// 剔除发消息的客户端

if (targetChannel instanceof SocketChannel

&& targetChannel != sourceChannel) {

try {

// 将信息发送到targetChannel客户端

((SocketChannel) targetChannel).write(

Charset.forName("UTF-8").encode(request));

} catch (IOException e) {

e.printStackTrace();

}

}

});

}

/**

* 主方法

* @param args

*/

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

new NioServer().start();

}

}

NIO客户端

public class NioClient {

/**

* 启动

*/

public void start(String nickname) throws IOException {

/**

* 连接服务器端

*/

SocketChannel socketChannel = SocketChannel.open(

new InetSocketAddress("127.0http://.0.1", 8000));

/**

* 接收服务器端响应

*/

// 新开线程,专门负责来接收服务器端的响应数据

// selector , socketChannel , 注册

Selector selector = Selector.open();

socketChannel.configureBlocking(false);

socketChannel.register(selector, SelectionKey.OP_READ);

new Thread(new NioClientHandler(selector)).start();

/**

* 向服务器端发送数据

*/

Scanner scanner = new Scanner(System.in);

while (scanner.hasNextLine()) {

String request = scanner.nextLine();

if (request != null && request.length() > 0) {

socketChannel.write(

Charset.forName("UTF-8")

.encode(nickname + " : " + request));

}

}

}

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

// new NioClient().start();

}

}

客户端线程,处理服务器端响应的的消息

public class NioClientHandler implements Runnable {

private Selector selector;

public NioClientHandler(Selector selector) {

this.selector = selector;

}

@Override

public void run() {

try {

for (;;) {

int readyChannels = selector.select();

if (readyChannels == 0) continue;

/**

* 获取可用channel的集合

*/

Set selectionKeys = selector.selectedKeys();

Iterator iterator = selectionKeys.iterator();

while (iterator.hasNext()) {

/**

* selectionKey实例

*/

SelectionKey selectionKey = (SelectionKey) iterator.next();

/**

* **移除Set中的当前selectionKey**

*/

iterator.remove();

/**

* 7. 根据就绪状态,调用对应方法处理业务逻辑

*/

/**

* 如果是 可读事件

*/

if (selectionKey.isReadable()) {

readHandler(selectionKey, selector);

}

}

}

} catch (IOException e) {

e.printStackTrace();

}

}

/**

* 可读事件处理器

*/

private void readHandler(SelectionKey selectionKey, Selector selector)

throws IOException {

/**

* 要从 selectionKey 中获取到已经就绪的channel

*/

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

/**

* 创建buffer

*/

ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

/**

* 循环读取服务器端响应信息

*/

String response = "";JBeQSXu

while (socketChannel.read(byteBuffer) > 0) {

/**

* 切换buffer为读模式

*/

byteBuffer.flip();

/**

* 读取buffer中的内容

*/

response += Charset.forName("UTF-8").decode(byteBuffer);

}

/**

* 将channel再次注册到selector上,监听他的可读事件

*/

socketChannel.regiJBeQSXuster(selector, SelectionKey.OP_READ);

/**

* 将服务器端响应信息打印到本地

*/

if (response.length() > 0) {

System.out.println(response);

}

}

}

我们定义三个客户端,模拟三个用户在聊天室发送消息

public class AClient {

public static void main(String[] args)

throws IOException {

new NioClient().start("AClient");

}

}

public class BClient {

public static void main(String[] args)

throws IOException {

new NioClient().start("BClient");

}

}

public class CClient {

public static void main(String[] args)

throws IOException {

new NioClient().start("CClient");

}

}

NIO 聊天室到此结束


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:004::每天五分钟入门TCP/IP协议栈::IP协议之16位总长度字段引出的MTU值问题
下一篇:HTTP协议详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~