Java NIO聊天窗口实例

开发 后端
本文主要给介绍了Java NIO聊天窗口的实例。

一、服务器

  1. package com.ww.server;  
  2.  
  3. import java.io.IOException;  
  4. import java.net.InetSocketAddress;  
  5. import java.nio.ByteBuffer;  
  6. import java.nio.channels.SelectionKey;  
  7. import java.nio.channels.Selector;  
  8. import java.nio.channels.ServerSocketChannel;  
  9. import java.nio.channels.SocketChannel;  
  10. import java.text.SimpleDateFormat;  
  11. import java.util.Date;  
  12. import java.util.Iterator;  
  13. import java.util.List;  
  14. import java.util.Vector;  
  15.  
  16. import com.ww.dao.UsersData;  
  17. import com.ww.entity.Users;  
  18.  
  19.  
  20. public class Server implements Runnable{  
  21.       
  22.     //选择器  
  23.     private Selector selector;  
  24.       
  25.     //选择key  
  26.     private SelectionKey sscKey;  
  27.       
  28.     //服务器开关  
  29.     private boolean isOpen;  
  30.       
  31.     //用户集合  
  32.     private List<Users> users;  
  33.       
  34.     //用户上线列表  
  35.     private Vector<String> userNames;  
  36.       
  37.     public Server(int port)  
  38.     {  
  39.         isOpen = true;  
  40.         users = UsersData.dataUsers();  
  41.         userNames = new Vector<String>();  
  42.         init(port);  
  43.     }  
  44.       
  45.       
  46.     @Override 
  47.     public void run()   
  48.     {  
  49.         try {  
  50.             while(isOpen)  
  51.             {  
  52.                 //接收信息的数量  
  53.                 int result = selector.select();  
  54.                 if(result > 0)  
  55.                 {  
  56.                     for (Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); iterator.hasNext();)   
  57.                     {  
  58.                         SelectionKey key = (SelectionKey) iterator.next();  
  59.                         iterator.remove();  
  60.                         //判断是否是接收状态  
  61.                         if(key.isAcceptable())  
  62.                         {  
  63.                             System.out.println("==========客户端开启==========");  
  64.                             getConn(key);  
  65.                         }  
  66.                         //判断是否是读取状态  
  67.                         else if(key.isReadable())  
  68.                         {  
  69.                             System.out.println("=============读取=============");  
  70.                             ReadMsg(key);  
  71.                         }  
  72.                         //判断是否是写入状态  
  73.                         else if(key.isWritable())  
  74.                         {  
  75.                             System.out.println("=============写入=============");  
  76.                             WriteMsg(key);  
  77.                         }  
  78.                           
  79.                     }  
  80.                 }  
  81.                   
  82.             }  
  83.         } catch (IOException e) {  
  84.             e.printStackTrace();  
  85.         }  
  86.     }  
  87.  
  88.     //初始化服务器  
  89.     private void init(int port)  
  90.     {  
  91.         try {  
  92.             //开启选择器  
  93.             selector = Selector.open();  
  94.             //开启ServerSocket  
  95.             ServerSocketChannel ssc = ServerSocketChannel.open();  
  96.             //设置非阻塞模式  
  97.             ssc.configureBlocking(false);  
  98.             //设置端口  
  99.             ssc.socket().bind(new InetSocketAddress(port));  
  100.             //注册到选择器里并设置为接收状态  
  101.             sscKey = ssc.register(selector,SelectionKey.OP_ACCEPT);  
  102.             System.out.println("==========开启服务器==========");  
  103.               
  104.         } catch (IOException e) {  
  105.             e.printStackTrace();  
  106.         }  
  107.     }  
  108.       
  109.     //获取连接  
  110.     private void getConn(SelectionKey key) throws IOException  
  111.     {  
  112.         //获取ServerSocket  
  113.         ServerSocketChannel ssc = (ServerSocketChannel)key.channel();  
  114.         //设置Socket  
  115.         SocketChannel sc = ssc.accept();  
  116.         //设置非阻塞模式  
  117.         sc.configureBlocking(false);  
  118.         //注册到选择器里并设置为读取状态  
  119.         sc.register(selector, SelectionKey.OP_READ);  
  120.     }  
  121.       
  122.     //读取信息  
  123.     private void ReadMsg(SelectionKey key) throws IOException  
  124.     {  
  125.         //获取到Socket  
  126.         SocketChannel sc = (SocketChannel)key.channel();  
  127.         ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024);  
  128.         buffer.clear();  
  129.         StringBuffer sb = new StringBuffer();  
  130.         //获取字节长度  
  131.         int count = sc.read(buffer);  
  132.         if( count > 0 )  
  133.         {  
  134.             buffer.flip();  
  135.             sb.append(new String(buffer.array(), 0, count));  
  136.         }  
  137.         Object obj = (Object)sb.toString();  
  138.         if(obj.toString().indexOf("-")!= -1)  
  139.         {  
  140.             //获取用户名  
  141.             String userName = obj.toString().substring(0, obj.toString().indexOf("-"));  
  142.             //获取用户密码  
  143.             String userPass = obj.toString().substring(obj.toString().indexOf("-") + 1);  
  144.               
  145.             boolean isTrue = false;  
  146.             //判断用户是否存在  
  147.             for (int i = 0; i < users.size(); i++) {  
  148.                 if(users.get(i).getUserName().equals(userName) && users.get(i).getUserPass().equals(userPass))  
  149.                 {  
  150.                     System.out.println("========" + userName + "登录成功========");  
  151.                     isTrue = true;  
  152.                     userNames.addElement(userName);  
  153.                     KeyAttach(key,"true");  
  154.                     break;  
  155.                 }  
  156.                 isTrue = false;  
  157.             }  
  158.               
  159.             //用户不存在  
  160.             if(!isTrue)  
  161.             {  
  162.                 System.out.println("========" + userName + "登录失败========");  
  163.                 KeyAttach(key,"false");  
  164.             }  
  165.         }  
  166.         else if(obj.toString().equals("open"))  
  167.         {  
  168.             System.out.println("=========开启聊天窗口=========");  
  169.             //给都有的用户返回用户列表  
  170.             AllKeysAttach(key,userNames);  
  171.         }  
  172.         else if( obj.toString().indexOf("exit_") != -1 )  
  173.         {  
  174.             String userName = obj.toString().substring(5);  
  175.             userNames.removeElement(userName);  
  176.             System.out.println("========" + userName + "退出窗体========");  
  177.             KeyAttach(key,"close");  
  178.             OtherKeysAttach(key,userNames);  
  179.         }  
  180.         else 
  181.         {  
  182.             //获取用户名  
  183.             String userName = obj.toString().substring(0,obj.toString().indexOf("^"));  
  184.             //获取信息  
  185.             String mess = obj.toString().substring(obj.toString().indexOf("^")+1);  
  186.             //获取发信时间  
  187.             SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");  
  188.             String dateTime = dateFormat.format(new Date());  
  189.             //设置信息  
  190.             String mss = userName + " " + dateTime + "\n" + mess + "\n";  
  191.             //给都有的用户返回聊天信息  
  192.             AllKeysAttach(key,mss);  
  193.         }  
  194.           
  195.     }  
  196.       
  197.     //所有client改成写入状态  
  198.     private void AllKeysAttach(SelectionKey key,Object obj)  
  199.     {  
  200.         for (Iterator<SelectionKey> iterator = key.selector().keys().iterator(); iterator.hasNext();)   
  201.         {  
  202.             SelectionKey selKey = (SelectionKey) iterator.next();  
  203.             //判断不是Server key;  
  204.             if( selKey != sscKey )  
  205.             {  
  206.                 selKey.attach(obj);  
  207.                 //把其他client改成可写状态  
  208.                 selKey.interestOps( selKey.interestOps() | SelectionKey.OP_WRITE );  
  209.             }  
  210.         }  
  211.     }  
  212.       
  213.     //把其他客户改成写入状态  
  214.     private void OtherKeysAttach(SelectionKey key,Object obj)  
  215.     {  
  216.         for (Iterator<SelectionKey> iterator = key.selector().keys().iterator(); iterator.hasNext();)   
  217.         {  
  218.             SelectionKey selKey = (SelectionKey) iterator.next();  
  219.             //判断不是本生client key和Server key;  
  220.             if( selKey != sscKey && selKey != key )  
  221.             {  
  222.                 selKey.attach(obj);  
  223.                 //把其他client改成可写状态  
  224.                 selKey.interestOps( selKey.interestOps() | SelectionKey.OP_WRITE );  
  225.             }  
  226.         }  
  227.     }  
  228.       
  229.     //自身改成写入状态  
  230.     private void KeyAttach(SelectionKey key,Object obj)  
  231.     {  
  232.         key.attach(obj);  
  233.         key.interestOps(SelectionKey.OP_WRITE);  
  234.     }  
  235.       
  236.     //发送信息  
  237.     private void WriteMsg(SelectionKey key) throws IOException  
  238.     {  
  239.         //获取到Socket  
  240.         SocketChannel sc = (SocketChannel)key.channel();  
  241.         //获取附属值  
  242.         Object obj = key.attachment();  
  243.         //把附属值设为空  
  244.         key.attach("");  
  245.         //发送信息  
  246.         sc.write(ByteBuffer.wrap(obj.toString().getBytes()));  
  247.         if(obj.toString().equals("close") || obj.toString().equals("false"))  
  248.         {  
  249.             key.cancel();  
  250.             sc.socket().close();  
  251.             sc.close();  
  252.             System.out.println("==========客户端关闭==========");  
  253.             return;  
  254.         }  
  255.         //设置为读取状态  
  256.         key.interestOps(SelectionKey.OP_READ);  
  257.     }  
  258.       
  259.     public static void main(String[] args)   
  260.     {     
  261.         Server server = new Server(8001);  
  262.         new Thread(server).start();  
  263.     }  

二、客户端界面

1.登录界面

  1. package com.ww.frame;  
  2.  
  3. import java.awt.Color;  
  4. import java.awt.Font;  
  5. import java.awt.event.ActionEvent;  
  6. import java.awt.event.ActionListener;  
  7. import java.awt.event.WindowAdapter;  
  8. import java.awt.event.WindowEvent;  
  9. import java.io.IOException;  
  10.  
  11. import javax.swing.JButton;  
  12. import javax.swing.JFrame;  
  13. import javax.swing.JLabel;  
  14. import javax.swing.JTextField;  
  15.  
  16. import com.ww.biz.ClientServerBIz;  
  17. import com.ww.frame.ChatFrame;  
  18.  
  19. public class LoginFrame {  
  20.       
  21.     private JLabel   
  22.         lblTitle = new JLabel("山寨版QQ"),  
  23.         lblUserName = new JLabel("用户名:"),  
  24.         lblPassword = new JLabel("密     码:");  
  25.       
  26.     private JTextField   
  27.         txtUserName = new JTextField(15),  
  28.         txtPassword = new JTextField(15);  
  29.       
  30.     private JButton  
  31.         btnSub = new JButton("提交"),  
  32.         btnRes = new JButton("取消");  
  33.       
  34.     private JFrame  
  35.         aFrame = new JFrame("登录山寨QQ");  
  36.       
  37.     private ClientServerBIz clientBiz;  
  38.     public LoginFrame()  
  39.     {  
  40.         into();  
  41.     }  
  42.       
  43.     private void into()  
  44.     {  
  45.         aFrame.setLayout(null);  
  46.         aFrame.setBounds(300300200180);  
  47.         lblTitle.setBounds(451010040);  
  48.         lblTitle.setForeground(new Color(120120120));  
  49.         lblTitle.setFont(new Font("山寨版QQ"120));  
  50.         aFrame.add(lblTitle);  
  51.         lblUserName.setBounds(10508020);  
  52.         aFrame.add(lblUserName);  
  53.         lblPassword.setBounds(10808020);  
  54.         aFrame.add(lblPassword);  
  55.         txtUserName.setBounds(655012020);  
  56.         aFrame.add(txtUserName);  
  57.         txtPassword.setBounds(658012020);  
  58.         aFrame.add(txtPassword);  
  59.         btnSub.setBounds(101108025);  
  60.         aFrame.add(btnSub);  
  61.         btnRes.setBounds(1001108025);  
  62.         aFrame.add(btnRes);  
  63.           
  64.         btnSub.addActionListener(new ActionListener() {  
  65.             @Override 
  66.             public void actionPerformed(ActionEvent e) {  
  67.                 String userInfo = txtUserName.getText() + "-" + txtPassword.getText();  
  68.                 try {  
  69.                     clientBiz = new ClientServerBIz();  
  70.                     clientBiz.sendToServer(userInfo);  
  71.                     Object obj = clientBiz.sendToClient();  
  72.                     System.out.println(obj.toString());  
  73.                     if (Boolean.parseBoolean(obj.toString()))  
  74.                     {  
  75.                         ChatFrame cf = new ChatFrame(clientBiz,txtUserName.getText());  
  76.                         cf.show();  
  77.                         aFrame.setVisible(false);  
  78.                     }  
  79.                     else 
  80.                     {  
  81.                         System.out.println("用户不存在或密码错误!");  
  82.                     }  
  83.                 } catch (IOException e1) {  
  84.                     e1.printStackTrace();  
  85.                 } catch (ClassNotFoundException e1) {  
  86.                     e1.printStackTrace();  
  87.                 }  
  88.             }  
  89.         });  
  90.           
  91.         btnRes.addActionListener(new ActionListener() {  
  92.             @Override 
  93.             public void actionPerformed(ActionEvent e) {  
  94.                 System.exit(0);  
  95.             }  
  96.         });  
  97.           
  98.         aFrame.addWindowListener(new WindowAdapter() {  
  99.             @Override 
  100.             public void windowClosing(WindowEvent e) {  
  101.                 System.exit(0);  
  102.             }     
  103.         });  
  104.     }  
  105.       
  106.     public void show()  
  107.     {  
  108.         aFrame.setVisible(true);  
  109.     }   
  110.       
  111.     public static void main(String[] args) {  
  112.         LoginFrame login = new LoginFrame();  
  113.         login.show();  
  114.     }  
  115.  

2.聊天界面

  1. package com.ww.frame;  
  2.  
  3. import java.awt.event.ActionEvent;  
  4. import java.awt.event.ActionListener;  
  5. import java.awt.event.WindowAdapter;  
  6. import java.awt.event.WindowEvent;  
  7. import java.io.IOException;  
  8.  
  9. import javax.swing.DefaultListModel;  
  10. import javax.swing.JButton;  
  11. import javax.swing.JFrame;  
  12. import javax.swing.JList;  
  13. import javax.swing.JOptionPane;  
  14. import javax.swing.JTextArea;  
  15. import javax.swing.event.ListSelectionEvent;  
  16. import javax.swing.event.ListSelectionListener;  
  17.  
  18. import com.ww.biz.ClientServerBIz;  
  19.  
  20. public class ChatFrame {  
  21.       
  22.     //文本框  
  23.     private JTextArea  
  24.         readContext = new JTextArea(18,30),//显示信息  
  25.         writeContext = new JTextArea(6,30);//发送信息  
  26.       
  27.     //列表框  
  28.     private DefaultListModel modle = new DefaultListModel();//列表模型  
  29.     private JList list = new JList(modle);//列表  
  30.       
  31.     //按钮  
  32.     private JButton   
  33.         btnSub = new JButton("提交"),//提交按钮  
  34.         btnRes = new JButton("取消");//取消按钮  
  35.       
  36.     //窗体界面  
  37.     private JFrame aFrame = new JFrame("ChatFrame");  
  38.       
  39.     //用户名  
  40.     private String userName;  
  41.       
  42.     //Client业务类  
  43.     private ClientServerBIz userBiz;  
  44.       
  45.     //设置线程是否运行  
  46.     private boolean isConntext = false;  
  47.       
  48.     //构造方法  
  49.     public ChatFrame(ClientServerBIz clientBiz,String userName)  
  50.     {  
  51.         //获取用户名  
  52.         this.userName = userName;  
  53.         userBiz = clientBiz;  
  54.         //开启线程  
  55.         isConntext = true;  
  56.         new Thread(new ctUsers()).start();    
  57.     }  
  58.       
  59.     //初始化界面  
  60.     private void init() throws IOException, ClassNotFoundException  
  61.     {  
  62.         aFrame.setLayout(null);  
  63.         aFrame.setTitle(userName+" 聊天窗口");  
  64.         aFrame.setSize(500500);  
  65.         aFrame.setLocation(400200);  
  66.         readContext.setBounds(1010320285);  
  67.         readContext.setEditable(false);  
  68.         writeContext.setBounds(10305320100);  
  69.         list.setBounds(34010140445);  
  70.         aFrame.add(readContext);  
  71.         aFrame.add(writeContext);  
  72.         aFrame.add(list);  
  73.         btnSub.setBounds(1504158030);  
  74.         btnRes.setBounds(2504158030);  
  75.           
  76.         //frame的关闭按钮事件  
  77.         aFrame.addWindowListener(new WindowAdapter() {  
  78.             @Override 
  79.             public void windowClosing(WindowEvent e) {  
  80.                 isConntext = false;  
  81.                 //发送关闭信息  
  82.                 userBiz.sendToServer("exit_" + userName);  
  83.                 System.exit(0);  
  84.             }  
  85.         });  
  86.  
  87.         //提交按钮事件  
  88.         btnSub.addActionListener(new ActionListener() {  
  89.             @Override 
  90.             public void actionPerformed(ActionEvent e) {  
  91.                 //发送信息  
  92.                 userBiz.sendToServer(userName + "^" + writeContext.getText());  
  93.                 writeContext.setText(null);  
  94.             }  
  95.         });  
  96.           
  97.         //关闭按钮事件  
  98.         btnRes.addActionListener(new ActionListener() {   
  99.             @Override 
  100.             public void actionPerformed(ActionEvent e) {  
  101.                 isConntext = false;  
  102.                 //发送关闭信息  
  103.                 userBiz.sendToServer("exit_" + userName);  
  104.                 System.exit(0);  
  105.             }  
  106.         });  
  107.           
  108.           
  109.         list.addListSelectionListener(new ListSelectionListener() {   
  110.             @Override 
  111.             public void valueChanged(ListSelectionEvent e) {  
  112.                 JOptionPane.showMessageDialog(null,list.getSelectedValue().toString());  
  113.             }  
  114.         });  
  115.           
  116.         aFrame.add(btnSub);  
  117.         aFrame.add(btnRes);  
  118.         aFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  119.     }  
  120.       
  121.     //界面显示  
  122.     public void show() throws IOException, ClassNotFoundException  
  123.     {  
  124.         init();  
  125.         aFrame.setVisible(true);  
  126.         userBiz.sendToServer("open");  
  127.     }  
  128.       
  129.     class ctUsers extends Thread  
  130.     {  
  131.         public void run()   
  132.         {  
  133.             while(isConntext)  
  134.             {  
  135.                 //获取服务器传过的值  
  136.                 Object obj = userBiz.sendToClient();  
  137.                   
  138.                 //判断值是否有空  
  139.                 if(obj != null)  
  140.                 {  
  141.                       
  142.                     if(obj.toString().indexOf("[") != -1 && obj.toString().lastIndexOf("]") != -1)  
  143.                     {  
  144.                         obj = obj.toString().substring(1, obj.toString().length()-1);  
  145.                         String [] userNames = obj.toString().split(",");  
  146.                         modle.removeAllElements();  
  147.                         for (int i = 0; i < userNames.length; i++) {  
  148.                             modle.addElement(userNames[i].trim());  
  149.                         }  
  150.                     }  
  151.                     else 
  152.                     {  
  153.                         String str = readContext.getText() + obj.toString();  
  154.                         readContext.setText(str);  
  155.                     }  
  156.                 }  
  157.             }  
  158.         }  
  159.     }  

三、客户端业务类

  1. package com.ww.biz;  
  2.  
  3. import java.io.IOException;  
  4. import java.net.InetSocketAddress;  
  5. import java.nio.ByteBuffer;  
  6. import java.nio.channels.SocketChannel;  
  7.  
  8.  
  9. public class ClientServerBIz {  
  10.       
  11.     private SocketChannel sc;  
  12.     public ClientServerBIz() throws IOException  
  13.     {  
  14.         sc = SocketChannel.open();  
  15.         sc.configureBlocking(false);  
  16.         sc.connect(new InetSocketAddress("localhost",8001));  
  17.     }  
  18.  
  19.     //发送信息到服务器  
  20.     public void sendToServer(Object obj)  
  21.     {  
  22.         try {  
  23.             while(!sc.finishConnect())  
  24.             {}  
  25.             sc.write(ByteBuffer.wrap(obj.toString().getBytes()));  
  26.         } catch (IOException e) {  
  27.             e.printStackTrace();  
  28.         }  
  29.     }  
  30.       
  31.     //获取服务器信息传递信息到客户端  
  32.     public Object sendToClient()  
  33.     {  
  34.         ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024);  
  35.         buffer.clear();  
  36.         StringBuffer sb = new StringBuffer();  
  37.         int count = 0;  
  38.         Object obj = null;  
  39.         try {  
  40.             //获取字节长度  
  41.             Thread.sleep(100);  
  42.             while ((count = sc.read(buffer)) > 0) {  
  43.                 sb.append(new String(buffer.array(), 0, count));  
  44.             }  
  45.             if( sb.length() > 0 )  
  46.             {  
  47.                 obj = sb.toString();  
  48.                 if("close".equals(sb.toString()))  
  49.                 {  
  50.                     obj = null;  
  51.                     sc.close();  
  52.                     sc.socket().close();  
  53.                 }  
  54.             }  
  55.         } catch (IOException e) {  
  56.             e.printStackTrace();  
  57.         } catch (InterruptedException e) {  
  58.             e.printStackTrace();  
  59.         }  
  60.         return obj;  
  61.     }  

四、数据源

  1. package com.ww.dao;  
  2.  
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.  
  6. import com.ww.entity.Users;  
  7.  
  8. public class UsersData {  
  9.     public static List<Users> dataUsers()  
  10.     {  
  11.         List<Users> users = new ArrayList<Users>();  
  12.         Users user1 = new Users("tiantian","123456");  
  13.         Users user2 = new Users("dongdong","123456");  
  14.         Users user3 = new Users("xiaoxiao","123456");  
  15.         Users user4 = new Users("mingming","123456");  
  16.         users.add(user1);  
  17.         users.add(user2);  
  18.         users.add(user3);  
  19.         users.add(user4);  
  20.         return users;  
  21.     }  

五、实体

  1. package com.ww.entity;  
  2.  
  3. import java.io.Serializable;  
  4.  
  5. public class Users implements Serializable{  
  6.     private String userName;  
  7.     private String userPass;  
  8.     public String getUserName() {  
  9.         return userName;  
  10.     }  
  11.     public void setUserName(String userName) {  
  12.         this.userName = userName;  
  13.     }  
  14.     public String getUserPass() {  
  15.         return userPass;  
  16.     }  
  17.     public void setUserPass(String userPass) {  
  18.         this.userPass = userPass;  
  19.     }  
  20.     public Users(String userName,String userPass)  
  21.     {  
  22.         this.userName = userName;  
  23.         this.userPass = userPass;  
  24.     }  

原文链接:http://love5845.iteye.com/blog/903597

【编辑推荐】

  1. Java NIO 经典实例代码
  2. Java NIO性能测试
  3. Java数据缓存实现的核心机制
  4. NIO需要了解的一些概念
  5. Java NIO TCP编程
责任编辑:林师授 来源: love5845的博客
相关推荐

2011-12-15 11:11:51

JavaNIO

2011-04-06 16:14:40

Delphi

2017-01-09 10:42:56

微信小程序

2021-11-05 13:20:43

微信个人状态移动应用

2011-12-15 11:19:08

JavaNIO

2011-12-15 10:10:33

Javanio

2011-12-07 14:41:51

JavaNIO

2010-07-08 10:28:51

UML接口

2011-12-08 09:37:36

JavaNIO

2021-07-27 12:21:34

微信Bug聊天记录

2023-08-29 18:23:46

代码AI

2014-01-02 10:46:35

PostgreSQLC++

2011-12-15 11:03:21

JavaNIO

2010-08-11 14:41:08

Flex窗口

2010-04-19 08:51:30

2009-06-30 16:26:56

2023-04-21 10:21:26

世优科技ChatGPT数字人

2011-12-15 09:40:06

Javanio

2009-08-31 17:35:12

C#接口实例

2011-12-07 14:57:44

JavaNIO
点赞
收藏

51CTO技术栈公众号