一、服务器
- package com.ww.server;
- 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.List;
- import java.util.Vector;
- import com.ww.dao.UsersData;
- import com.ww.entity.Users;
- public class Server implements Runnable{
- //选择器
- private Selector selector;
- //选择key
- private SelectionKey sscKey;
- //服务器开关
- private boolean isOpen;
- //用户集合
- private List<Users> users;
- //用户上线列表
- private Vector<String> userNames;
- public Server(int port)
- {
- isOpen = true;
- users = UsersData.dataUsers();
- userNames = new Vector<String>();
- init(port);
- }
- @Override
- public void run()
- {
- try {
- while(isOpen)
- {
- //接收信息的数量
- int result = selector.select();
- if(result > 0)
- {
- for (Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); iterator.hasNext();)
- {
- SelectionKey key = (SelectionKey) iterator.next();
- iterator.remove();
- //判断是否是接收状态
- if(key.isAcceptable())
- {
- System.out.println("==========客户端开启==========");
- getConn(key);
- }
- //判断是否是读取状态
- else if(key.isReadable())
- {
- System.out.println("=============读取=============");
- ReadMsg(key);
- }
- //判断是否是写入状态
- else if(key.isWritable())
- {
- System.out.println("=============写入=============");
- WriteMsg(key);
- }
- }
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- //初始化服务器
- private void init(int port)
- {
- try {
- //开启选择器
- selector = Selector.open();
- //开启ServerSocket
- ServerSocketChannel ssc = ServerSocketChannel.open();
- //设置非阻塞模式
- ssc.configureBlocking(false);
- //设置端口
- ssc.socket().bind(new InetSocketAddress(port));
- //注册到选择器里并设置为接收状态
- sscKey = ssc.register(selector,SelectionKey.OP_ACCEPT);
- System.out.println("==========开启服务器==========");
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- //获取连接
- private void getConn(SelectionKey key) throws IOException
- {
- //获取ServerSocket
- ServerSocketChannel ssc = (ServerSocketChannel)key.channel();
- //设置Socket
- SocketChannel sc = ssc.accept();
- //设置非阻塞模式
- sc.configureBlocking(false);
- //注册到选择器里并设置为读取状态
- sc.register(selector, SelectionKey.OP_READ);
- }
- //读取信息
- private void ReadMsg(SelectionKey key) throws IOException
- {
- //获取到Socket
- SocketChannel sc = (SocketChannel)key.channel();
- ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024);
- buffer.clear();
- StringBuffer sb = new StringBuffer();
- //获取字节长度
- int count = sc.read(buffer);
- if( count > 0 )
- {
- buffer.flip();
- sb.append(new String(buffer.array(), 0, count));
- }
- Object obj = (Object)sb.toString();
- if(obj.toString().indexOf("-")!= -1)
- {
- //获取用户名
- String userName = obj.toString().substring(0, obj.toString().indexOf("-"));
- //获取用户密码
- String userPass = obj.toString().substring(obj.toString().indexOf("-") + 1);
- boolean isTrue = false;
- //判断用户是否存在
- for (int i = 0; i < users.size(); i++) {
- if(users.get(i).getUserName().equals(userName) && users.get(i).getUserPass().equals(userPass))
- {
- System.out.println("========" + userName + "登录成功========");
- isTrue = true;
- userNames.addElement(userName);
- KeyAttach(key,"true");
- break;
- }
- isTrue = false;
- }
- //用户不存在
- if(!isTrue)
- {
- System.out.println("========" + userName + "登录失败========");
- KeyAttach(key,"false");
- }
- }
- else if(obj.toString().equals("open"))
- {
- System.out.println("=========开启聊天窗口=========");
- //给都有的用户返回用户列表
- AllKeysAttach(key,userNames);
- }
- else if( obj.toString().indexOf("exit_") != -1 )
- {
- String userName = obj.toString().substring(5);
- userNames.removeElement(userName);
- System.out.println("========" + userName + "退出窗体========");
- KeyAttach(key,"close");
- OtherKeysAttach(key,userNames);
- }
- else
- {
- //获取用户名
- String userName = obj.toString().substring(0,obj.toString().indexOf("^"));
- //获取信息
- String mess = obj.toString().substring(obj.toString().indexOf("^")+1);
- //获取发信时间
- SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
- String dateTime = dateFormat.format(new Date());
- //设置信息
- String mss = userName + " " + dateTime + "\n" + mess + "\n";
- //给都有的用户返回聊天信息
- AllKeysAttach(key,mss);
- }
- }
- //所有client改成写入状态
- private void AllKeysAttach(SelectionKey key,Object obj)
- {
- for (Iterator<SelectionKey> iterator = key.selector().keys().iterator(); iterator.hasNext();)
- {
- SelectionKey selKey = (SelectionKey) iterator.next();
- //判断不是Server key;
- if( selKey != sscKey )
- {
- selKey.attach(obj);
- //把其他client改成可写状态
- selKey.interestOps( selKey.interestOps() | SelectionKey.OP_WRITE );
- }
- }
- }
- //把其他客户改成写入状态
- private void OtherKeysAttach(SelectionKey key,Object obj)
- {
- for (Iterator<SelectionKey> iterator = key.selector().keys().iterator(); iterator.hasNext();)
- {
- SelectionKey selKey = (SelectionKey) iterator.next();
- //判断不是本生client key和Server key;
- if( selKey != sscKey && selKey != key )
- {
- selKey.attach(obj);
- //把其他client改成可写状态
- selKey.interestOps( selKey.interestOps() | SelectionKey.OP_WRITE );
- }
- }
- }
- //自身改成写入状态
- private void KeyAttach(SelectionKey key,Object obj)
- {
- key.attach(obj);
- key.interestOps(SelectionKey.OP_WRITE);
- }
- //发送信息
- private void WriteMsg(SelectionKey key) throws IOException
- {
- //获取到Socket
- SocketChannel sc = (SocketChannel)key.channel();
- //获取附属值
- Object obj = key.attachment();
- //把附属值设为空
- key.attach("");
- //发送信息
- sc.write(ByteBuffer.wrap(obj.toString().getBytes()));
- if(obj.toString().equals("close") || obj.toString().equals("false"))
- {
- key.cancel();
- sc.socket().close();
- sc.close();
- System.out.println("==========客户端关闭==========");
- return;
- }
- //设置为读取状态
- key.interestOps(SelectionKey.OP_READ);
- }
- public static void main(String[] args)
- {
- Server server = new Server(8001);
- new Thread(server).start();
- }
- }
二、客户端界面
1.登录界面
- package com.ww.frame;
- import java.awt.Color;
- import java.awt.Font;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.awt.event.WindowAdapter;
- import java.awt.event.WindowEvent;
- import java.io.IOException;
- import javax.swing.JButton;
- import javax.swing.JFrame;
- import javax.swing.JLabel;
- import javax.swing.JTextField;
- import com.ww.biz.ClientServerBIz;
- import com.ww.frame.ChatFrame;
- public class LoginFrame {
- private JLabel
- lblTitle = new JLabel("山寨版QQ"),
- lblUserName = new JLabel("用户名:"),
- lblPassword = new JLabel("密 码:");
- private JTextField
- txtUserName = new JTextField(15),
- txtPassword = new JTextField(15);
- private JButton
- btnSub = new JButton("提交"),
- btnRes = new JButton("取消");
- private JFrame
- aFrame = new JFrame("登录山寨QQ");
- private ClientServerBIz clientBiz;
- public LoginFrame()
- {
- into();
- }
- private void into()
- {
- aFrame.setLayout(null);
- aFrame.setBounds(300, 300, 200, 180);
- lblTitle.setBounds(45, 10, 100, 40);
- lblTitle.setForeground(new Color(120, 120, 120));
- lblTitle.setFont(new Font("山寨版QQ", 1, 20));
- aFrame.add(lblTitle);
- lblUserName.setBounds(10, 50, 80, 20);
- aFrame.add(lblUserName);
- lblPassword.setBounds(10, 80, 80, 20);
- aFrame.add(lblPassword);
- txtUserName.setBounds(65, 50, 120, 20);
- aFrame.add(txtUserName);
- txtPassword.setBounds(65, 80, 120, 20);
- aFrame.add(txtPassword);
- btnSub.setBounds(10, 110, 80, 25);
- aFrame.add(btnSub);
- btnRes.setBounds(100, 110, 80, 25);
- aFrame.add(btnRes);
- btnSub.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- String userInfo = txtUserName.getText() + "-" + txtPassword.getText();
- try {
- clientBiz = new ClientServerBIz();
- clientBiz.sendToServer(userInfo);
- Object obj = clientBiz.sendToClient();
- System.out.println(obj.toString());
- if (Boolean.parseBoolean(obj.toString()))
- {
- ChatFrame cf = new ChatFrame(clientBiz,txtUserName.getText());
- cf.show();
- aFrame.setVisible(false);
- }
- else
- {
- System.out.println("用户不存在或密码错误!");
- }
- } catch (IOException e1) {
- e1.printStackTrace();
- } catch (ClassNotFoundException e1) {
- e1.printStackTrace();
- }
- }
- });
- btnRes.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- System.exit(0);
- }
- });
- aFrame.addWindowListener(new WindowAdapter() {
- @Override
- public void windowClosing(WindowEvent e) {
- System.exit(0);
- }
- });
- }
- public void show()
- {
- aFrame.setVisible(true);
- }
- public static void main(String[] args) {
- LoginFrame login = new LoginFrame();
- login.show();
- }
- }
2.聊天界面
- package com.ww.frame;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.awt.event.WindowAdapter;
- import java.awt.event.WindowEvent;
- import java.io.IOException;
- import javax.swing.DefaultListModel;
- import javax.swing.JButton;
- import javax.swing.JFrame;
- import javax.swing.JList;
- import javax.swing.JOptionPane;
- import javax.swing.JTextArea;
- import javax.swing.event.ListSelectionEvent;
- import javax.swing.event.ListSelectionListener;
- import com.ww.biz.ClientServerBIz;
- public class ChatFrame {
- //文本框
- private JTextArea
- readContext = new JTextArea(18,30),//显示信息
- writeContext = new JTextArea(6,30);//发送信息
- //列表框
- private DefaultListModel modle = new DefaultListModel();//列表模型
- private JList list = new JList(modle);//列表
- //按钮
- private JButton
- btnSub = new JButton("提交"),//提交按钮
- btnRes = new JButton("取消");//取消按钮
- //窗体界面
- private JFrame aFrame = new JFrame("ChatFrame");
- //用户名
- private String userName;
- //Client业务类
- private ClientServerBIz userBiz;
- //设置线程是否运行
- private boolean isConntext = false;
- //构造方法
- public ChatFrame(ClientServerBIz clientBiz,String userName)
- {
- //获取用户名
- this.userName = userName;
- userBiz = clientBiz;
- //开启线程
- isConntext = true;
- new Thread(new ctUsers()).start();
- }
- //初始化界面
- private void init() throws IOException, ClassNotFoundException
- {
- aFrame.setLayout(null);
- aFrame.setTitle(userName+" 聊天窗口");
- aFrame.setSize(500, 500);
- aFrame.setLocation(400, 200);
- readContext.setBounds(10, 10, 320, 285);
- readContext.setEditable(false);
- writeContext.setBounds(10, 305, 320, 100);
- list.setBounds(340, 10, 140, 445);
- aFrame.add(readContext);
- aFrame.add(writeContext);
- aFrame.add(list);
- btnSub.setBounds(150, 415, 80, 30);
- btnRes.setBounds(250, 415, 80, 30);
- //frame的关闭按钮事件
- aFrame.addWindowListener(new WindowAdapter() {
- @Override
- public void windowClosing(WindowEvent e) {
- isConntext = false;
- //发送关闭信息
- userBiz.sendToServer("exit_" + userName);
- System.exit(0);
- }
- });
- //提交按钮事件
- btnSub.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- //发送信息
- userBiz.sendToServer(userName + "^" + writeContext.getText());
- writeContext.setText(null);
- }
- });
- //关闭按钮事件
- btnRes.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- isConntext = false;
- //发送关闭信息
- userBiz.sendToServer("exit_" + userName);
- System.exit(0);
- }
- });
- list.addListSelectionListener(new ListSelectionListener() {
- @Override
- public void valueChanged(ListSelectionEvent e) {
- JOptionPane.showMessageDialog(null,list.getSelectedValue().toString());
- }
- });
- aFrame.add(btnSub);
- aFrame.add(btnRes);
- aFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- }
- //界面显示
- public void show() throws IOException, ClassNotFoundException
- {
- init();
- aFrame.setVisible(true);
- userBiz.sendToServer("open");
- }
- class ctUsers extends Thread
- {
- public void run()
- {
- while(isConntext)
- {
- //获取服务器传过的值
- Object obj = userBiz.sendToClient();
- //判断值是否有空
- if(obj != null)
- {
- if(obj.toString().indexOf("[") != -1 && obj.toString().lastIndexOf("]") != -1)
- {
- obj = obj.toString().substring(1, obj.toString().length()-1);
- String [] userNames = obj.toString().split(",");
- modle.removeAllElements();
- for (int i = 0; i < userNames.length; i++) {
- modle.addElement(userNames[i].trim());
- }
- }
- else
- {
- String str = readContext.getText() + obj.toString();
- readContext.setText(str);
- }
- }
- }
- }
- }
- }
三、客户端业务类
- package com.ww.biz;
- import java.io.IOException;
- import java.net.InetSocketAddress;
- import java.nio.ByteBuffer;
- import java.nio.channels.SocketChannel;
- public class ClientServerBIz {
- private SocketChannel sc;
- public ClientServerBIz() throws IOException
- {
- sc = SocketChannel.open();
- sc.configureBlocking(false);
- sc.connect(new InetSocketAddress("localhost",8001));
- }
- //发送信息到服务器
- public void sendToServer(Object obj)
- {
- try {
- while(!sc.finishConnect())
- {}
- sc.write(ByteBuffer.wrap(obj.toString().getBytes()));
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- //获取服务器信息传递信息到客户端
- public Object sendToClient()
- {
- ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024);
- buffer.clear();
- StringBuffer sb = new StringBuffer();
- int count = 0;
- Object obj = null;
- try {
- //获取字节长度
- Thread.sleep(100);
- while ((count = sc.read(buffer)) > 0) {
- sb.append(new String(buffer.array(), 0, count));
- }
- if( sb.length() > 0 )
- {
- obj = sb.toString();
- if("close".equals(sb.toString()))
- {
- obj = null;
- sc.close();
- sc.socket().close();
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- return obj;
- }
- }
四、数据源
- package com.ww.dao;
- import java.util.ArrayList;
- import java.util.List;
- import com.ww.entity.Users;
- public class UsersData {
- public static List<Users> dataUsers()
- {
- List<Users> users = new ArrayList<Users>();
- Users user1 = new Users("tiantian","123456");
- Users user2 = new Users("dongdong","123456");
- Users user3 = new Users("xiaoxiao","123456");
- Users user4 = new Users("mingming","123456");
- users.add(user1);
- users.add(user2);
- users.add(user3);
- users.add(user4);
- return users;
- }
- }
五、实体
- package com.ww.entity;
- import java.io.Serializable;
- public class Users implements Serializable{
- private String userName;
- private String userPass;
- public String getUserName() {
- return userName;
- }
- public void setUserName(String userName) {
- this.userName = userName;
- }
- public String getUserPass() {
- return userPass;
- }
- public void setUserPass(String userPass) {
- this.userPass = userPass;
- }
- public Users(String userName,String userPass)
- {
- this.userName = userName;
- this.userPass = userPass;
- }
- }
原文链接:http://love5845.iteye.com/blog/903597
【编辑推荐】