Java NIO实现简单聊天室(GUI版)
登录界面:
package com.chatroom;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import com.chat.client.ChatFrame;
import com.chat.client.ClientService;
/*
* 登录聊天室
*/
public class LoginFrame extends JFrame{
static final long serialVersionUID = 1L;
static JTextField txtName;
static JButton btnOK;
static JLabel label;
public LoginFrame() {
this.setLayout(null);
Toolkit kit = Toolkit.getDefaultToolkit();
int w = kit.getScreenSize().width;
int h = kit.getScreenSize().height;
this.setBounds(w / 2 - 230 / 2, h / 2 - 200 / 2, 230, 200);
this.setTitle("设置名称");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setResizable(false);
txtName = new JTextField(4);
this.add(txtName);
txtName.setBounds(10, 10, 100, 25);
btnOK = new JButton("OK");
this.add(btnOK);
btnOK.setBounds(120, 10, 80, 25);
label = new JLabel("[w:" + w + ",h:" + h + "]");
this.add(label);
label.setBounds(10, 40, 200, 100);
label.setText("<html>在上面的文本框中输入名字<br/>显示器宽度:" + w + "<br/>显示器高度:" + h
+ "</html>");
btnOK.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String uname = txtName.getText();
ClientService service = ClientService.getInstance();
ChatFrame chatFrame = new ChatFrame(service, uname);
chatFrame.show();
setVisible(false);
}
});
}
public static void main(String[] args) {
LoginFrame loginFrame = new LoginFrame();
loginFrame.setVisible(true);
}
}
服务端:
package com.chatroom;
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.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Vector;
public class ChatServer implements Runnable{
Selector selector;
SelectionKey selectionKey;
boolean isRunning;
Vector<String> usernames;//用来存放用户的名字
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public ChatServer(int port) throws IOException {
isRunning = true;
usernames = new Vector<>();
init(port);
}
private void printInfo(String str) {
System.out.println("[" + sdf.format(new Date()) + "] -> " + str);
}
/*
* 初始化,启动服务器
*/
public void init(int port) throws IOException {
selector=Selector.open();
ServerSocketChannel server = ServerSocketChannel.open();
server.socket().bind(new InetSocketAddress(port));
server.configureBlocking(false);
selectionKey = server.register(selector, SelectionKey.OP_ACCEPT);
printInfo("启动服务器");
}
@Override
public void run() {
try {
while (isRunning) {
int n=selector.select();
if (n>0) {
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
/*
* 如有客户端进来则进行连接
*/
if (key.isAcceptable()) {
ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
SocketChannel socketChannel = serverSocketChannel.accept();
if (socketChannel==null) {
continue;
}
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
}
if (key.isReadable()) {
readMsg(key);
}
if (key.isWritable()) {
writeMsg(key);
}
}
}
}
} catch (Exception e) {
// TODO: handle exception
}
}
/*
* 读取信息
*/
public void readMsg(SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
StringBuffer sBuffer = new StringBuffer();
int count = socketChannel.read(buffer);//读取从客户端传过来的信息大小
/*
* 如果有信息则加到StringBuffer中
*/
if (count>0) {
buffer.flip();
sBuffer.append(new String(buffer.array(), 0, count));
}
/*将信息转换成字符串*/
String string = sBuffer.toString();
/*
* 处理用户上线的情况
*/
if (string.indexOf("open_") != -1) {
String name = string.substring(5);
printInfo(name+"上线");
usernames.add(name);
Iterator<SelectionKey> sIterator = selector.selectedKeys().iterator();
while (sIterator.hasNext()) {
SelectionKey keyss = sIterator.next();
if (keyss!=selectionKey) {
keyss.attach(usernames);
keyss.interestOps(keyss.interestOps() | SelectionKey.OP_WRITE);
}
}
/*
* 处理用户下线的情况
*/
} else if (string.indexOf("exit_") != -1) {
String username = string.substring(5);
usernames.remove(username);
key.attach("close");
key.interestOps(SelectionKey.OP_WRITE);
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey sKey = iterator.ne