首页 > 其他 > 详细

NIO练习,实现简单的聊天室

时间:2020-06-13 20:13:54      阅读:36      评论:0      收藏:0      [点我收藏+]

该练习分为两部分,服务端和客户端,当一个客户端连接到服务端时,服务端将获取到客户端,并将客户端注册到选择器中 ,当客户端发送信息时,服务端将获取到客户端发送的信息,并将该信息转发给其他的客户端,实现消息的传输。对于客户端来说 则能向发送消息和读取消息,这些都是通过channel selector和bytebuffer实现的 具体代码如下:

客户端:

public class GroupChatClient {
//定义相关属性
private final String HOST="127.0.0.1";
private final int PORT=8848;
private String userName;
private Selector selector;
private SocketChannel socketChannel;
//构造器
public GroupChatClient() throws IOException {
selector = Selector.open();
socketChannel=SocketChannel.open(new InetSocketAddress(HOST,PORT));
//设置非阻塞
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
userName=socketChannel.getLocalAddress().toString().substring(1);
System.out.println(userName+"准备好了");
}
//向服务器发送消息
public void sendInfo(String msg){
String info=userName+"说:"+msg;
try {
socketChannel.write(ByteBuffer.wrap(msg.getBytes()));
}catch (IOException e){
e.printStackTrace();
}
}
//读取服务器的消息
public void readInfo(){
try{
int readChannels=selector.select(2000);
if(readChannels>0){
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()){
SelectionKey selectionKey = iterator.next();
if(selectionKey.isReadable()){
//得到当前通道
SocketChannel channel =(SocketChannel) selectionKey.channel();
//得到缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//读取通道内容
channel.read(byteBuffer);
//转成字符串
String s = new String(byteBuffer.array());
System.out.println(s);
}
else{
System.out.println("没有可用的通道");
}
iterator.remove();
}
}
}
catch (IOException e){
e.printStackTrace();
}
}

public static void main(String[] args) throws IOException {
//启动客户端
GroupChatClient groupChatClient=new GroupChatClient();
//启动一个线程
new Thread(){
public void run(){
//每隔三秒读取数据
while (true){
try {
groupChatClient.readInfo();
Thread.currentThread().sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
//发送数据给服务器
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()){
String s=scanner.nextLine();
groupChatClient.sendInfo(s);
}
}
}
服务端:
public class GroupChatServer {
//定义属性
private ServerSocketChannel listener;
private Selector selector;
private static final int PORT = 8848;
private IOException e;

//构造器初始化操作
public GroupChatServer() {
try {
//得到选择器
selector = Selector.open();
//ServerSocketChannel
listener = ServerSocketChannel.open();
//绑定端口
listener.socket().bind(new InetSocketAddress(PORT));
//设置非阻塞模式
listener.configureBlocking(false);
//将ServerSocketChannel注册到Selector上
listener.register(selector, SelectionKey.OP_ACCEPT);

} catch (IOException e) {
e.printStackTrace();
}
}

//监听
public void listener() {
try {
//循环监听
while (true) {
if (selector.select() == 0) {
System.out.println("等待中");
continue;
}
//遍历得到的SelectionKeys
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey next = iterator.next();
//监听到连接事件
if (next.isAcceptable()) {
SocketChannel socketChannel = listener.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
System.out.println(socketChannel.getRemoteAddress() + "上线了");
}
if (next.isReadable()) {
//发生可读事件
readData(next);
}
}
//删除key 防止重复处理
iterator.remove();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
//读取客户端信息
private void readData(SelectionKey key) throws IOException {
//获取到通道
SocketChannel socketChannel = null;
try {
socketChannel= (SocketChannel) key.channel();
//获取缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
int count = socketChannel.read(byteBuffer);
if (count > 0) {
String msg=new String(byteBuffer.array());
System.out.println(msg);
//向其他客户端转发
sendInfoToOther(msg,socketChannel);
}
} catch (IOException e) {
e.printStackTrace();
System.out.println(socketChannel.getRemoteAddress()+"离线了");
//取消注册并关闭通道
key.channel();
socketChannel.close();
}
}
//转发消息给客户(通道)
private void sendInfoToOther(String msg, SocketChannel slef) throws IOException {
System.out.println("服务器转发消息");
//遍历所有注册到selector的通道 并排除自己
for (SelectionKey key : selector.keys()) {
//通过key 获得对应的通道
Channel channel = key.channel();
//排除自己
if (channel instanceof SocketChannel && channel != slef) {
SocketChannel socketChannel = (SocketChannel) channel;
ByteBuffer byteBuffer = ByteBuffer.wrap(msg.getBytes());
socketChannel.write(byteBuffer);
}
}
}
public static void main(String[] args) {
//创建一个服务器对象
GroupChatServer groupChatServer = new GroupChatServer();
groupChatServer.listener();
}
}

NIO练习,实现简单的聊天室

原文:https://www.cnblogs.com/mc-74120/p/13121412.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!