赞
踩
一:业务逻辑
二:类设计及代码结构
三:代码
Mymessage类代码:
package objtalk; import java.io.Serializable; import java.util.ArrayList; import javax.swing.text.StyledDocument; /* * 该消息类分为两种 * 一种是实际消息内容 * 还有一种是当前群聊的成员信息 * */ public class MyMessage implements Serializable {// 序列化&&反序列化(用于被传输的对象) public static final long serialVersionUID = 1l; public static final int MES_TYPE_PLAIN = 1;//文本消息 public static final int MES_TYPE_UPDATE_CLIENTLIST = 2;//更新用户列表消息 private StyledDocument content ;//非文本消息(例如图片) private ArrayList<String> clientList;//当前群聊成员信息 private int mesType = -1; private boolean ifmass=true;//判断是群聊消息还是私聊信息 private String ip="null";//私发message对象ip private String usename = "null"; public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public MyMessage(Boolean ifmass,int mesType) { this.ifmass=ifmass; this.mesType = mesType; } public int getMesType() { return mesType; } public void setMesType(int mesType) { this.mesType = mesType; } public StyledDocument getContent() { return content; } public void setContent(StyledDocument content) { this.content = content; } public ArrayList<String> getClientList() { return clientList; } public void setClientList(ArrayList<String> clientList) { this.clientList = clientList; } public boolean getisIfmass() { return ifmass; } public void setIfmass(boolean ifmass) { this.ifmass = ifmass; } }
signup类代码:
package objtalk; /*创建一张talk数据表 * 表结构为usename和password * */ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import javax.swing.JButton; import javax.swing.JEditorPane; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JTextField; import com.mysql.jdbc.Connection; import com.mysql.jdbc.Statement; public class signup extends JFrame{ private JTextField usename = new JTextField();//文本输入框 private JTextField password = new JTextField(); private JButton signup = new JButton("注册");//按钮 private JButton signin = new JButton("登陆"); //数据库信息 private String user = ""; private String pwd = ""; private String url = "";//jdbc:myaql://ip或端口号/需要打开的database private boolean tag = false;//判断账号密码是否正确 public signup() { // TODO Auto-generated constructor stub this.setSize(300,400); this.setLocationRelativeTo(null); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setLayout(null); this.add(usename); this.add(password); this.add(signin); this.add(signup); usename.setSize(100,30); password.setSize(100,30); signin.setSize(100,50); signup.setSize(100,50); usename.setLocation(100,100); password.setLocation(100,200); signin.setLocation(50,300); signup.setLocation(150,300); try { Class.forName("com.mysql.jdbc.Driver");//开启数据库 } catch (ClassNotFoundException e2) { // TODO Auto-generated catch block e2.printStackTrace(); } signin.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String useName = usename.getText().toString(); String passWord = password.getText().toString(); if(useName.isEmpty()||passWord.isEmpty()){ JOptionPane.showMessageDialog(null, "请输入用户名或密码", "error",JOptionPane.ERROR_MESSAGE); } else{ try { Connection con = (Connection) DriverManager.getConnection(url, user, pwd);//数据库连 Statement stmt = (Statement) con.createStatement();//创建语句对象 String sql = "select * from talk";//数据库语句 ResultSet rs = (ResultSet) stmt.executeQuery(sql);//执行语句得到结果,以行的角度表现查询结果 java.sql.ResultSetMetaData rsmd = rs.getMetaData();//结果以列的形式展现 while(rs.next()){//按行逐个读取查询的内容,next()表示行的移动 if(rs.getString(1).equals(useName)&&rs.getString(2).equals(passWord)){ tag = true; new SocketFrame().setVisible(true);//跳转到主界面 exits();//关闭当前界面 return; } } if(tag==false){ JOptionPane.showMessageDialog(null, "账号密码错误!", "error",JOptionPane.ERROR_MESSAGE); } } catch (SQLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } }); signup.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub String useName = usename.getText().toString(); String passWord = password.getText().toString(); if(useName.isEmpty()||passWord.isEmpty()){ JOptionPane.showMessageDialog(null, "请输入用户名或密码", "error",JOptionPane.ERROR_MESSAGE); } else{ Connection con; try { con = (Connection) DriverManager.getConnection(url, user, pwd); Statement stmt = (Statement) con.createStatement(); String sql = "insert talk value('"+useName+"','"+passWord+"');"; stmt.executeUpdate(sql); JOptionPane.showMessageDialog(null,"注册成功", "done",JOptionPane.ERROR_MESSAGE); //stmt.executeQuery(sql);//执行语句得到结果,以行的角度表现查询结果 } catch (SQLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); }//数据库连接,Connection是接口不能用new } } }); } public void exits() { this.setVisible(false); } public static void main(String[] args) { new signup().setVisible(true); } }
SocktFrame类代码
package objtalk; import java.awt.BorderLayout; import java.awt.Font; import java.awt.Image; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.BufferedWriter; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.Socket; import java.net.SocketAddress; import java.nio.channels.NonWritableChannelException; import java.nio.channels.SelectableChannel; import java.util.ArrayList; import java.util.List; import javax.imageio.ImageIO; import javax.lang.model.element.Element; import javax.swing.AbstractListModel; import javax.swing.DefaultListModel; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.JTextPane; import javax.swing.event.AncestorListener; import javax.swing.event.ListSelectionListener; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.text.BadLocationException; import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants; import javax.swing.text.StyledDocument; public class SocketFrame extends JFrame { private JTextPane jtpMes = new JTextPane();//消息框 private StyledDocument contentDoc = jtpMes.getStyledDocument();//取出文本(),属性定义(sas的容器) private JScrollPane jspMes = new JScrollPane(jtpMes);//为消息框添加滑动框 private JButton btnSend = new JButton("Send"); private JButton btnConnect = new JButton("Connect"); private JButton btnSelectimg = new JButton("img"); private JTextPane jtpNewMes = new JTextPane();//消息框(可以显示图片和文字) private JScrollPane jspNewMes = new JScrollPane(jtpNewMes);//为群聊框添加滑动框 private StyledDocument sendDoc = jtpNewMes.getStyledDocument(); private JPanel panSend = new JPanel(); JPanel btnPan = new JPanel(); private Font font = new Font("宋体", Font.PLAIN, 20); private JList<String> listClient = new JList<>(); private JScrollPane jspClientList = new JScrollPane(listClient); private Socket socket; private ObjectOutputStream out; private ReadThread reader;//读取消息线程 public SocketFrame() { this.setSize(800, 600); this.setLocationRelativeTo(null); this.setDefaultCloseOperation(EXIT_ON_CLOSE); init(); getContentPane().add(jspMes); getContentPane().add(panSend, BorderLayout.SOUTH); getContentPane().add(jspClientList, BorderLayout.EAST); } public void updateListClient(ArrayList list) {//跟新群聊用户信息 listClient.setModel(new ClientListModel(list)); } class ClientListModel extends AbstractListModel {//更新list信息 ArrayList list; public ClientListModel(ArrayList list) { super(); this.list = list; } @Override public Object getElementAt(int arg0) { return list.get(arg0); } @Override public int getSize() { return list.size(); } } private void init() { panSend.setLayout(new BorderLayout()); panSend.add(jspNewMes,BorderLayout.CENTER); panSend.add(btnPan,BorderLayout.EAST); btnPan.add(btnSend); btnPan.add(btnConnect); btnPan.add(btnSelectimg); jtpMes.setEditable(false); jtpMes.setFont(font); jtpNewMes.setFont(font); btnSend.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { String str = jtpNewMes.getText().trim();//得到文本 System.out.println(str); if (str != null && str.length() > 0 && socket != null) { SocketAddress address = socket.getRemoteSocketAddress();//得到本地地址 String ip = address.toString().substring(1, address.toString().indexOf(":") + 1);//获得ip SimpleAttributeSet sas = new SimpleAttributeSet();//容器存储消息体 StyleConstants.setFontSize(sas,24);//设置字体 try { /*senDoc消息内容会自动从输入消息框获取(绑定更新,50行57行代码实现),这里只是在消息前面添加ip(类似用户名)*/ sendDoc.insertString(0, ip, sas); } catch (BadLocationException e) { // TODO Auto-generated catch block e.printStackTrace(); } MyMessage mes = new MyMessage(true,MyMessage.MES_TYPE_PLAIN); mes.setContent(sendDoc); sendMes(mes);//发送消息 try { sendDoc.remove(0, sendDoc.getLength());//去除容器中的内容 } catch (BadLocationException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }); btnConnect.addActionListener(new ActionListener() {//连接服务器 @Override public void actionPerformed(ActionEvent arg0) { if(socket==null){ try { socket = new Socket("10.117.45.114", 12345);//具体ip自己设置 reader = new ReadThread(socket); reader.start(); out = new ObjectOutputStream(socket.getOutputStream());//创建消息输入流 } catch (Exception e) { e.printStackTrace(); } } } }); btnSelectimg.addActionListener(new ActionListener() {//选区本地图片存入容器 @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub JFileChooser fc = new JFileChooser("d:");//文件选择器 FileNameExtensionFilter filter = new FileNameExtensionFilter("JPG & GIF Image", "jpg","gif");//文件筛选器 fc.setFileFilter(filter); int i = fc.showOpenDialog(SocketFrame.this); if(i == JFileChooser.APPROVE_OPTION){ try { Image img = ImageIO.read(fc.getSelectedFile()); ImageIcon icon = new ImageIcon(img); SimpleAttributeSet sas = new SimpleAttributeSet();//容器 StyleConstants.setIcon(sas, icon);//把图标放入sas容器 sendDoc.insertString(sendDoc.getLength(), "icon", sas);//把sas插入文本格式,属性定义 } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (BadLocationException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } }); this.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent arg0) {//关闭主界面后程序退出流关闭 if (out != null) { MyMessage mes = new MyMessage(true,MyMessage.MES_TYPE_PLAIN); //mes.setContent("quit"); sendMes(mes); reader.stopRun(); } } }); listClient.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { // TODO Auto-generated method stub super.mouseClicked(e); if(e.getClickCount()==2){//双击触发私聊 new PrivateDialog(listClient.getSelectedValue().toString()).setVisible(true); } } }); } public void append(StyledDocument sd){ int caretPosition = jtpMes.getStyledDocument().getLength(); caretPosition+=sd.getLength(); try { for(int i=0;i<sd.getLength();i++){ javax.swing.text.Element e = sd.getCharacterElement(i); if(e.getName().equals("icon")){ contentDoc.insertString(contentDoc.getLength(), "icon", e.getAttributes()); i+=2; } else{ String s = sd.getText(i, 1); contentDoc.insertString(contentDoc.getLength(), s, e.getAttributes()); } } contentDoc.insertString(contentDoc.getLength(), "\n", null); } catch (BadLocationException e) { // TODO Auto-generated catch block e.printStackTrace(); } jtpMes.setCaretPosition(caretPosition); } public void sendMes(MyMessage m) { if (out != null) { try { out.reset();//反复发送同一个内容不断改变的对象需要使用reset(此时为sendDoc) out.writeObject(m); out.flush(); } catch (IOException e) { e.printStackTrace(); } } } class ReadThread extends Thread { Socket c; boolean flag = true; public ReadThread(Socket c) { this.c = c; } @Override public void run() { try { ObjectInputStream in = new ObjectInputStream((c.getInputStream())); MyMessage newMes = (MyMessage) in.readObject(); while (flag) { switch (newMes.getMesType()) { case MyMessage.MES_TYPE_PLAIN: append(newMes.getContent());//将得到的消息添加进聊天框 break; case MyMessage.MES_TYPE_UPDATE_CLIENTLIST: updateListClient(newMes.getClientList());//更新聊天人信息 break; } //将输入流和message对象初始化供下次使用 in = new ObjectInputStream((c.getInputStream())); newMes = (MyMessage) in.readObject(); } } catch (Exception e) { e.printStackTrace(); } } public void stopRun() { flag = false; } } class PrivateDialog extends JDialog{//单独对话框 private JTextPane jtpPriMes = new JTextPane(); private JScrollPane jspPriMes = new JScrollPane(jtpPriMes); private JButton btnPriSend = new JButton("Send"); private JButton btnselect = new JButton("select"); private JPanel panFun = new JPanel(); private String ip; public PrivateDialog(String ip) { // TODO Auto-generated constructor stub this.ip = ip; this.setTitle(ip); this.setSize(400, 300); this.setLocationRelativeTo(null); init(); this.add(panFun); } private void init() { panFun.add(jtpPriMes); panFun.add(btnPriSend); panFun.add(btnselect); btnPriSend.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub String str = jtpPriMes.getText().trim(); if(str!=null&&str.length()>0&&socket!=null){ MyMessage mes = new MyMessage(false,MyMessage.MES_TYPE_PLAIN); mes.setIp(ip); mes.setContent(jtpPriMes.getStyledDocument()); sendMes(mes); } } }); btnselect.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub JFileChooser fc = new JFileChooser("d:"); FileNameExtensionFilter filter = new FileNameExtensionFilter("JPG & GIF Image", "jpg","gif");//文件筛选器 fc.setFileFilter(filter); int i = fc.showOpenDialog(SocketFrame.this); if(i == JFileChooser.APPROVE_OPTION){ try { Image img = ImageIO.read(fc.getSelectedFile()); ImageIcon icon = new ImageIcon(img); SimpleAttributeSet sas = new SimpleAttributeSet();//容器 StyleConstants.setIcon(sas, icon);//把图标放入sas容器 jtpPriMes.getStyledDocument().insertString(jtpPriMes.getStyledDocument().getLength(), "icon", sas);//把sas插入文本格式,属性定义 } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (BadLocationException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } }); } } }
ServerSocketTest代码
package objtalk; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketAddress; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants; import javax.swing.text.StyledDocument; import org.omg.CORBA.SystemException; public class ServerSocketTest { ServerSocket server; HashSet<Socket> clientSet = new HashSet<>(); public ServerSocketTest() { try { server = new ServerSocket(12345); } catch (IOException e) { e.printStackTrace(); } } public void work() { int no = 0;//连接服务器的个数 try { while (true) { Socket client = server.accept(); clientSet.add(client); SendUpdateClientList(); no++; new ClientThread(client, no).start(); } } catch (IOException e) { e.printStackTrace(); } } public void SendUpdateClientList() {//发送用户变更的消息,用户退出和加入的监听 MyMessage mes = new MyMessage(true,MyMessage.MES_TYPE_UPDATE_CLIENTLIST); mes.setClientList(getClientList()); massMes(mes); } public void massMes(MyMessage mes) {//群发消息 Iterator<Socket> it = clientSet.iterator(); while (it.hasNext()) { sendMes(it.next(), mes); } } public void singleMes(MyMessage mes){//单发消息 for(Socket s : clientSet){ if(s.getRemoteSocketAddress().toString().equals(mes.getIp())){//String判等必须用equals sendMes(s, mes); break; } } } public void sendMes(Socket s, MyMessage mes) { ObjectOutputStream out; try { out = new ObjectOutputStream(s.getOutputStream()); out.writeObject(mes); out.flush(); } catch (IOException e1) { e1.printStackTrace(); } } public ArrayList<String> getClientList() { ArrayList<String> list = null; if (clientSet.size() > 0) { list = new ArrayList<String>(); Iterator<Socket> it = clientSet.iterator(); int index = 0; while (it.hasNext()) { list.add(it.next().getRemoteSocketAddress().toString()); } } return list; } class ClientThread extends Thread { Socket c; int no; public ClientThread(Socket c, int no) { super(); this.c = c; this.no = no; } @Override public void run() { try (ObjectInputStream in = new ObjectInputStream((c.getInputStream()));) { MyMessage newMes = (MyMessage) in.readObject(); while (newMes.getContent()!=null) {//不断接收发来的消息 if(newMes.getisIfmass()==true){ massMes(newMes); System.out.println(newMes.getContent().getText(0,newMes.getContent().getLength() )); } else{ singleMes(newMes); } newMes = (MyMessage) in.readObject(); } } catch (Exception e) { e.printStackTrace(); } finally { try { c.close(); } catch (IOException e) { e.printStackTrace(); } clientSet.remove(c);//用户退出后 SendUpdateClientList(); } } } public static void main(String[] args) { new ServerSocketTest().work(); } }
四:使用方法:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。