基于NIO编写简易的群聊系统
服务器端
- 接收客户端的连接
- 接收客户端发送的消息并转发给其他所有客户端
public class ChatServer {
private Selector selector;
private ServerSocketChannel serverSocketChannel;
private static final int port = 8888;
public ChatServer() {
try {
selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.bind(new InetSocketAddress(port));
serverSocketChannel.configureBlocking(false);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
} catch (IOException e) {
e.printStackTrace();
}
}
public void listen() {
try {
while (true) {
int count = selector.select();
if (count > 0) {
Set<SelectionKey> keySet = selector.selectedKeys();
Iterator<SelectionKey> it = keySet.iterator();
while (it.hasNext()) {
SelectionKey key = it.next();
if (key.isAcceptable()) {
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector,SelectionKey.OP_READ);
// 提示上线
System.out.println(socketChannel.getRemoteAddress() + " 上线了!");
}
if (key.isReadable()) {
readData(key);
}
it.remove();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void readData(SelectionKey key){
SocketChannel socketChannel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
try {
int count = socketChannel.read(buffer);
if (count > 0) {
String msg = new String(buffer.array());
System.out.println("from 客户端 " + msg);
sendToOtherClient(msg,socketChannel); // 发给其他客户端去掉自己
}
} catch (IOException e) {
try {
System.out.println(socketChannel.getRemoteAddress() + " 离线了!");
key.cancel();
socketChannel.close();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
private void sendToOtherClient(String msg, SocketChannel myself) throws IOException {
for (SelectionKey key : selector.keys()) {
Channel sc = key.channel();
if (sc instanceof SocketChannel && sc != myself) {
SocketChannel target = (SocketChannel) sc;
ByteBuffer byteBuffer = ByteBuffer.wrap(msg.getBytes());
target.write(byteBuffer);
}
}
}
public static void main(String[] args) {
ChatServer server = new ChatServer();
server.listen();
}
}
客户端
- 一个线程不断地读取服务端地消息
- 一个线程不断向服务端发送消息
public class ChatClient {
private final static String HOST = "127.0.0.1";
private final static int PORT = 8888;
private Selector selector;
private SocketChannel socketChannel;
private String username;
public ChatClient() 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();
System.out.println(username + " is ok!");
}
// 向服务端发送消息
private void sendInfo(String info) throws IOException {
info = username + " " + info;
socketChannel.write(ByteBuffer.wrap(info.getBytes()));
}
// 向服务端读取消息
private void readInfo() throws IOException {
int readChannel = selector.select();
if (readChannel > 0) {
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
if (key.isReadable()) {
SocketChannel sc = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
sc.read(buffer);
String msg = new String(buffer.array());
System.out.println(msg.trim());
}
iterator.remove();
}
}
}
public static void main(String[] args) throws IOException {
ChatClient client = new ChatClient();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
client.readInfo();
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
String s = scanner.nextLine();
client.sendInfo(s);
}
}
}
编写完毕后,开启一个服务端和三个客户端,三个客户端依次发送消息"hello",运行结果为:
- 服务端
- 客户端1
- 客户端2
- 客户端3