Java NIO实现聊天室功能

网友投稿 308 2022-09-13


Java NIO实现聊天室功能

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

代码里面已经包含了必要的注释,这里不详述了。实现了基本的聊天室功能。

常量类:

public class Constant {

public static final int serverPort = 44444;

}

服务端:

package server;

import java.io.IOException;

import java.net.InetSocketAddress;

import java.net.SocketAddress;

import java.nio.ByteBuffer;

import java.nio.channels.ClosedChannelException;

import java.nio.channels.SelectionKey;

import java.nio.channels.Selector;

import java.nio.channels.ServerSocketChannel;

import java.nio.channels.SocketChannel;

import java.nio.charset.Charset;

import java.util.Iterator;

import java.util.Set;

import constant.Constant;

public class SocketServer {

private Charset charset = Charset.forName("UTF-8");

private ServerSocketChannel serverSocketChannel;

private Selector serverSocketSelector;

private SelectionKey serverRegisterKey;

private ByteBuffer buffer = ByteBuffer.allocate(1024);

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

new SocketServer().openServer(new InetSocketAddress(Constant.serverPort));

}

public void openServer(SocketAddress address) throws IOException {

init(address);

handle();

}

private void init(SocketAddress address) throws IOException {

serverSocketSelector = Selector.open();

serverSocketChannel = ServerSocketChannel.open();

serverSocketChannel.configureBlocking(false);

serverRegisterKey = serverSocketChannel.register(serverSocketSelector, SelectionKey.OP_ACCEPT);

serverSocketChannel.socket().bind(address);

}

private void handle() throws IOException {

System.out.println("服务端open");

while (serverSocketSelector.select() > 0) {

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

// 为什么这里要用迭代器,而不用增强for循环之类的呢?是因为这里获得一个key之后,要对其进行移除,避免二次处理,造成影响

while (iterator.hasNext()) {

dispatch(iterator.next());

iterator.remove();

}

}

}

private void dispatch(SelectionKey key) throws IOException {

if (key.isAcceptable()) {

accept(key);

} else if (key.isReadable()) {

readMessage(key);

} else if (key.isValid() && key.isWritable()) {

writeMessage(key);

}

}

private void accept(SelectionKey key) throws IOException, ClosedChannelException {

// 主要的是,接收事件是发生在服务器这边的,所以这边的通道要强转为ServerSocketChannel

ServerSocketChannel server = (ServerSocketChannel) key.channel();

SocketChannel client = server.accept();

client.configureBlocking(false);

// 同时再给该通道注册选择器,监听的内容的读取

client.register(serverSocketSelector, SelectionKey.OP_READ);

}

private void readMessage(SelectionKey key) throws IOException {

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

client.read(buffer);

// 调整为读取模式

buffer.flip();

String content = charset.decode(buffer).toString();

// 压缩空间,即抛弃已经读取的内容(实际上还在里面,只是处于等待被覆盖状态)

buffer.compact();

// 这里可以根据业务逻辑,设置不设置都可以,但是这里想接受到消息后立马回复一条消息,所以设置下一次感兴趣的(监听)事件为写

key.interestOps(SelectionKey.OP_WRITE);

// 设置系统回复信息

key.attach("系统已经收到你的消息\n");

// 开始广播这个客户端的内容到其他客户端

broadcast(key, content);

}

private void broadcast(SelectionKey self, String content) throws IOException {

Set selectedKeys = self.selector(http://).keys();

for (SelectionKey key : selectedKeys) {

// 不能发送给自己,也不要服务器自己本身对这个有反应

if (key != self && key != serverRegisterKey) {

String oldMessage = (String) key.attach(null);

// 如果有旧消息的话,在下一次发送时,连同旧消息一起发送

key.attach(oldMessage != null ? oldMessage + content : content);

key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);

}

}

}

private void writeMessage(SelectionKey key) throws IOException {

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

// 获取发给这个客户端的消息,并清空消息

client.write(charset.encode((String) key.attach(null)));

key.interestOps(SelectionKey.OP_READ);

}

}

客户端(包含了Socket版本和SocketChannel版本):

package client;

import java.io.IOException;

import java.net.InetSocketAddress;

import java.net.Socket;

import java.net.UnknownHostException;

import java.nio.ByteBuffer;

import java.nio.channels.SocketChannel;

import java.nio.charset.Charset;

import java.util.Scanner;

import constant.Constant;

public class SocketClient {

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

nioVersion();

// ioVersion();

}

private static void ioVersion() throws UnknownHostException, IOException {

System.out.println("客户端");

final Socket socket = new Socket();

socket.connect(new InetSocketAddress(Constant.serverPort));

new Thread() {

@Override

public void run() {

Scanner scanner = new Scanner(System.in);

while (scanner.hasNext()) {

String line = scanner.nextLine();

try {

socket.getOutputStream().write((line + "\n").getBytes("UTF-8"));

} catch (IOException e) {

e.printStackTrace();

}

}

scanner.close();

try {

socket.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

};

}.start();

new Thread() {

@Override

public void run() {

try {

Scanner scanner = new Scanner(socket.getInputStream(), "utf-8");

while (scanner.hasNext()) {

String line = scanner.nextLine();

System.out.println("收到消息:" + line);

}

scanner.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}.start();

}

private static void nioVersion() throws IOException {

Charset charset = Charset.forName("UTF-8");

System.out.println("客户端");

SocketChannel socketChannel = SocketChannel.open();

// 设置为非阻塞模式

socketChannel.configureBlocking(false);

socketChannel.connect(new InetSocketAddress(Constant.serverPort));

while (true) {

if (socketChannel.finishConnect()) {

new Thread() {

@Override

publiNyisfVkgMsc vohttp://id run() {

Scanner scanner = new Scanner(System.in);

while (scanner.hasNext()) {

String input = scanner.nextLine();

try {

socketChannel.write(charset.encode(input));

} catch (IOException e) {

e.printStackTrace();

}

}

scanner.close();

}

}.start();

new Thread() {

ByteBuffer dst = ByteBuffer.allocate(1024);

@Override

public void run() {

while (true) {

try {

int len = socketChannel.read(dst);

if (len > 0) {

dst.flip();

System.out.println("收到消息:" + charset.decode(dst));

dst.compact();

}

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}.start();

return;

}

}

}

}


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

上一篇:CCNA学习笔记:网络设备
下一篇:网络协议概述(简述什么是网络协议)
相关文章

 发表评论

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