JAVA UDP聊天室
2015-08-21 19:37
441 查看
本文为使用UDP 进行数据传输的一个聊天室应用,使用JAVA语言开发的聊天室在目前的实际中应用很少,写这个例子的原因的进一步理解CS模式编程,掌握这种思想。
本例子分为客户端和服务器两个部分,客户端输入想要发送给的对象(IP地址)已经要发送的数据,发到服务器中,服务器对发送来的数据进行解析后转发到相应的客户端,客户端与客户端之间不进行直接的通讯,而是由服务器转发,本例子中的服务器转发部分可以再优化(如果不优化,在用户量大的时候转发效率非常低,这个在实际运用时再实际修改),客户端实现的是通过服务器向指定的客户端发送消息(实际运用中可以使用网段发送,即是向指定网段的所有客户端发消息),服务器则可以向所有的在线客户端推送消息。在例子中的一个主要思想是客户端与客户端的通讯须经过服务器端,相当于要在服务器过滤之后才进行发送。在实际的应用中客户端不能知道另一个客户端的IP地址,但是每个客户端的知道服务器的IP,我们可以用一些唯一标识(比如账号或者用户名)来标识我们的每个客户端,这样每个客户端只要知道对方的账号就可以进行通信了。
好了,不说那么多了,直接上代码,
虽然些得渣渣的,但也是自己一笔一字码出来的,望各位大神指点指点。
服务器端的代码
客户端的代码:
用户类
本例子分为客户端和服务器两个部分,客户端输入想要发送给的对象(IP地址)已经要发送的数据,发到服务器中,服务器对发送来的数据进行解析后转发到相应的客户端,客户端与客户端之间不进行直接的通讯,而是由服务器转发,本例子中的服务器转发部分可以再优化(如果不优化,在用户量大的时候转发效率非常低,这个在实际运用时再实际修改),客户端实现的是通过服务器向指定的客户端发送消息(实际运用中可以使用网段发送,即是向指定网段的所有客户端发消息),服务器则可以向所有的在线客户端推送消息。在例子中的一个主要思想是客户端与客户端的通讯须经过服务器端,相当于要在服务器过滤之后才进行发送。在实际的应用中客户端不能知道另一个客户端的IP地址,但是每个客户端的知道服务器的IP,我们可以用一些唯一标识(比如账号或者用户名)来标识我们的每个客户端,这样每个客户端只要知道对方的账号就可以进行通信了。
好了,不说那么多了,直接上代码,
虽然些得渣渣的,但也是自己一笔一字码出来的,望各位大神指点指点。
服务器端的代码
package com.gxuwz.fulunyong; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.util.ArrayList; import java.util.List; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JTextArea; import javax.swing.JTextField; /** * @author:fulunyong * @email:fulunyong@qq.com * @datetime:2015年8月21日下午7:55:00 * @version 1.0 * @serial 服务器 */ public class ChatServer extends JFrame implements ActionListener{ private static final long serialVersionUID = 4717084330471059797L; private Integer port=2999;//系统端口 private JTextArea info;//客户端发来的消息 private JTextField msg;//推送的消息 private JButton send;//推送按钮 private List<User> users;//系统列表 private DatagramSocket socket;//传输介质 public ChatServer(){ setTitle("千锋聊天室-服务器"); setSize(400, 600);//设置窗体的大小 setLocationRelativeTo(null);//居中出现 setDefaultCloseOperation(EXIT_ON_CLOSE);//点击关闭时推出程序 //组件初始化 info=new JTextArea(); info.setEditable(false); msg=new JTextField(); send=new JButton("推送"); send.addActionListener(this);//给按钮添加监听器 this.add(info, BorderLayout.CENTER);//把消息显示框添加到窗体的居中位置 JPanel jPanel=new JPanel(new BorderLayout());//新建一个使用盒式布局的面板 jPanel.add(msg, BorderLayout.CENTER);//把消息输入框添加到面板居中位置 jPanel.add(send, BorderLayout.EAST);//把推送按钮添加到面板的东方向 this.add(jPanel, BorderLayout.SOUTH);//把面板添加到窗体的南方向。 //初始化数据报套接字 try { socket=new DatagramSocket(port); } catch (SocketException e){ e.printStackTrace(); return;//如果出现异常,程序退出,窗体不应该再显示。 } users=new ArrayList<User>();// info.append("服务器启动成功,等待客户端连接。。。\n");//执行到这里证明已经成功启动服务器。 setVisible(true);//显示窗体 byte[] bt=new byte[1024*64]; //循环读取并转发客户端的连接及发送的数据 while(true){ DatagramPacket packet=new DatagramPacket(bt, bt.length); try { socket.receive(packet); } catch (IOException e1){ e1.printStackTrace(); } if (null!=packet){ User tempuser=new User(packet.getAddress().toString().substring(1), packet.getPort()); if (!users.contains(tempuser)){// users.add(tempuser); } String temp=new String(packet.getData(), 0, packet.getLength()); String targetIp=temp.substring(0, temp.indexOf(":")); String str=temp.substring(temp.indexOf(":")+1); info.append(packet.getAddress().toString().substring(1)+" 对 "+targetIp+" 说:\n"); info.append(str+"\n"); for(int i = 0; i <users.size(); i++){ User user=users.get(i); if(targetIp.equals(user.getUserIp())){//查找消息接收对象 byte[] bs=(packet.getAddress().toString().substring(1)+temp.substring(temp.indexOf(":"))).getBytes(); try { DatagramPacket datagramPacket=new DatagramPacket(bs, bs.length, InetAddress.getByName(user.getUserIp()), user.getUserPort()); socket.send(datagramPacket); } catch (Exception e) { e.printStackTrace(); } } } } } } @Override public void actionPerformed(ActionEvent e){ String command=e.getActionCommand(); //推送按钮事件,服务器主动给所有用户发送消息。 if("推送".equals(command)){ for(int i = 0; i <users.size(); i++){ User user=users.get(i); String str="服务器:"+msg.getText(); byte[] bs=str.getBytes(); try { DatagramPacket packet=new DatagramPacket(bs, bs.length, InetAddress.getByName(user.getUserIp()), user.getUserPort()); socket.send(packet); } catch (Exception e1){ e1.printStackTrace(); } } } } public static void main(String[] args){ new ChatServer(); } }
客户端的代码:
package com.gxuwz.fulunyong; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JTextArea; import javax.swing.JTextField; /** * @author:fulunyong * @email:fulunyong@qq.com * @datetime:2015年8月21日下午7:56:25 * @version 1.0 * @serial 客户端 */ public class ChatClient extends JFrame { private static final long serialVersionUID = -4460571879641744285L; private JTextField toIp;//所要发送消息的对象 private JTextArea info;//消息显示框 private JTextField msg;//要发送的消息 private JButton send;//发送按钮 private DatagramSocket socket;//数据报套接字 private Integer port=6688;//客户端的端口 private Integer serverPort=2999;//服务器的端口,根据服务器实际端口修改 private String serverIp="10.16.151.90";//服务器IP 根据具体IP修改 public ChatClient(){ setTitle("千锋聊天室-客户端");//设置标题 setSize(400, 600);//设置窗口大小 setLocationRelativeTo(null);//居中出现 setDefaultCloseOperation(EXIT_ON_CLOSE);//关闭时推出 //组件初始化 toIp=new JTextField("127.0.0.1");//默认发送的IP,默认是本机,可以在客户端修改 info=new JTextArea(); info.setEditable(false);//禁用编辑 msg=new JTextField(); send=new JButton("发送"); //给发送按钮添加事件 send.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e){ String str=toIp.getText()+":"+msg.getText(); byte[] buf=str.getBytes(); try { //拼装数据报 DatagramPacket packet=new DatagramPacket(buf, buf.length, InetAddress.getByName(serverIp), serverPort); socket.send(packet);//发送数据报 } catch (Exception e1) { e1.printStackTrace(); } info.append("我说:"+msg.getText()+"\n"); msg.setText("");//清空消息输入框 msg.requestFocus();//获取鼠标焦点 } }); this.add(toIp,BorderLayout.NORTH);//添加IP输入框到窗体的北方向。 this.add(info,BorderLayout.CENTER);//添加消息显示框到居中位置 JPanel panel=new JPanel(new BorderLayout());//新建使用盒式布局的面板 panel.add(msg, BorderLayout.CENTER);//把消息输入框添加到面板的居中位置 panel.add(send, BorderLayout.EAST);//把发送按钮添加到面板的东方向 this.add(panel, BorderLayout.SOUTH);//把面板添加到窗体的南方向 //启动数据报套接字 try { socket=new DatagramSocket(port); } catch (SocketException e1){ e1.printStackTrace(); return;//如果出错,程序退出。 } setVisible(true);//显示窗体 byte[] bs=new byte[1024*64];//新建字节数组暂存数据 DatagramPacket packet=new DatagramPacket(bs, bs.length);//新建一个数据报对象 //循环读取服务器发来的消息。 while(true){ try { socket.receive(packet);//读取消息 if(null!=packet){//不为空就显示的消息显示框 String str=new String(packet.getData(), 0, packet.getLength()); info.append(str+"\n"); } } catch (IOException e1) { e1.printStackTrace(); } } } public static void main(String[] args){ new ChatClient(); } }
用户类
package com.gxuwz.fulunyong; import java.io.Serializable; /** * @author:fulunyong * @email:fulunyong@qq.com * @datetime:2015年8月21日下午8:00:29 * @version 1.0 * @serial 用户 */ public class User implements Serializable{ private static final long serialVersionUID =-2059184085514940866L; private String userIp; private Integer userPort; public User(){ } public User(String userIp, Integer userPort) { this.userIp = userIp; this.userPort = userPort; } public String getUserIp() { return userIp; } public void setUserIp(String userIp) { this.userIp = userIp; } public Integer getUserPort() { return userPort; } public void setUserPort(Integer userPort) { this.userPort = userPort; } @Override public String toString() { return "User [userIp=" + userIp + ", userPort=" + userPort + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((userIp == null) ? 0 : userIp.hashCode()); result = prime * result + ((userPort == null) ? 0 : userPort.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; User other = (User) obj; if (userIp == null) { if (other.userIp != null) return false; } else if (!userIp.equals(other.userIp)) return false; if (userPort == null) { if (other.userPort != null) return false; } else if (!userPort.equals(other.userPort)) return false; return true; } }
相关文章推荐
- 可视化Java垃圾回收
- Spring @PostConstruct and @PreDestroy example
- 尚硅谷公开课--struts2--7--通配映射
- Java三大常用布局管理器
- JAVA12个最重要的J2EE最佳实践
- java静态绑定和动态绑定小结
- JAVA运行程序代码段
- Java 中注意的细节之List.remove(int location)方法的使用
- Java IO体系结构
- java设计模式—原型模式
- 大龄屌丝自学笔记--Java零基础到菜鸟--007
- java第一课 helloword
- HDU 1850 Being a Good Boy in Spring Festival
- Java中的动态绑定和静态绑定
- java 遍历MAP
- 《Java设计模式》之访问者模式
- JAVA生成Word文档(经过测试)
- JAVA用freemarker生成复杂Excel。(freemarker)
- 《Java设计模式》之迭代模式
- java中main方法的详解