Java NIO基于控制台的多人聊天室

闲来无事写了个基于NIO的聊天室项目,费话不说了,直接贴代码吧。

Server端代码如下:

package com.xz.helloworld.nettyt.nio.im;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Channel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * Server端
 * @author yuxuan
 *
 */
public class GroupChatServer {

	private Selector selector;
	private ServerSocketChannel lisntenChannel;
	private static final Integer PORT = 6667;

	public GroupChatServer() {
		
		try {
			//获取选择器
			selector = Selector.open();
			
			lisntenChannel = ServerSocketChannel.open();
			
			lisntenChannel.socket().bind(new InetSocketAddress(PORT));
			
			lisntenChannel.configureBlocking(false);
			
			lisntenChannel.register(selector, SelectionKey.OP_ACCEPT);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	public void listen() {
		
		try {
			for(;;) {
				
				//count > 0 有事件
				int count = selector.select();
				if(count > 0) {
					
					//遍历得到的selectionKey集合
					Set<SelectionKey> selectionKeys = selector.selectedKeys();
					Iterator<SelectionKey> it = selectionKeys.iterator();
					
					while(it.hasNext()) {
						SelectionKey key = it.next();
						
						//删除当前的KEY,防止重复处理
						it.remove();
						
						//通道发生链接
						if(key.isAcceptable()) {
							SocketChannel socketChannel = lisntenChannel.accept();
							socketChannel.configureBlocking(false);
							socketChannel.register(selector, SelectionKey.OP_READ);
							System.out.println(socketChannel.getRemoteAddress() + " 上线了 ");
						}
						
						//通道发生read事件
						if(key.isReadable()) {
							readData(key);
						}
					}
					
				}else {
					System.out.println("wait...");
				}
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	private void readData(SelectionKey key) {
		
		SocketChannel channel = null;
		try {
			channel = (SocketChannel) key.channel();
			ByteBuffer buffer = ByteBuffer.allocate(1024);
			int count = channel.read(buffer);
			if(count > 0) {
				String msg = new String(buffer.array());
				System.out.println("from client :" + msg);
				
				//向其他的客户端转发消息
				sendMsgToOtherClients(msg,channel);
			}
			
		} catch (IOException e) {
			try {
				System.out.println(channel.getRemoteAddress() + "离线");
				//取消Key注册
				key.cancel();
				//关闭Channel
				channel.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
	}
	
	//转发消息给其他通道
	private void sendMsgToOtherClients(String msg,SocketChannel self) {
		
		try {
			System.out.println("server trans msg......");
			for(SelectionKey key :selector.keys()) {
				//通过Key取出对应的SocketChannel
				Channel transChannel = key.channel();
				if( transChannel instanceof SocketChannel &&  transChannel != self) {
					SocketChannel socketChannel = (SocketChannel) transChannel;
					socketChannel.write(ByteBuffer.wrap(msg.getBytes()));
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		GroupChatServer group = new GroupChatServer();
		group.listen();
	}
}

Client端如下:

package com.xz.helloworld.nettyt.nio.im;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Scanner;

public class GroupChatClient {

	private final String HOST = "127.0.0.1";
	private final Integer 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().substring(1);
			System.out.println(username + " is ok ......");
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void sendInfo(String info) {
		info = username + "说 :" + info;
		try {
			socketChannel.write(ByteBuffer.wrap(info.getBytes()));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void readInfo() {
		try {
			int readChannels = selector.select();
			if(readChannels > 0) {
				//说明有可用的通道
				
				Iterator<SelectionKey> it = selector.selectedKeys().iterator();
				while(it.hasNext()) {
					SelectionKey key = it.next();
					it.remove();
					if(key.isReadable()) {
						SocketChannel channel = (SocketChannel) key.channel();
						ByteBuffer buffer = ByteBuffer.allocate(1024);
						channel.read(buffer);
						String msg = new String(buffer.array());
						System.out.println(msg.trim());
					}
				}
			}else {
				System.out.println("no channel ...");
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	public static void main(String[] args) {
		
		GroupChatClient client = new GroupChatClient();
		
		//启动一个线程
		new Thread() {
			public void run() {
				for(;;) {
					client.readInfo();
					try {
						Thread.currentThread().sleep(3000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
//						e.printStackTrace();
					}
				}
			}
		}.start();
		
		//从客户端输入
		Scanner sc = new Scanner(System.in);
		while(sc.hasNextLine()) {
			String s = sc.nextLine();
			client.sendInfo(s);
		}
	}
}

以上就是聊天室的全部代码了,初学NIO的朋友可以参考来学习,先运行Server端,在开启几个Client端就可以看到效果了。

有问题可以在下方评论,技术问题可以私聊。

发布了106 篇原创文章 · 获赞 101 · 访问量 56万+

猜你喜欢

转载自blog.csdn.net/qq_24434671/article/details/103296942
今日推荐