要求:
udp实现聊天室,要求服务端只负责好友列表的刷新,不负责消息的转发

服务端:
1.服务端监听的是3000端口,其他用户统一对3000进行监听,实现实时的好友列表更新;

2.好友列表list和listb分别存放客户端的ip地址端口

 private ArrayList<String> lista = new ArrayList<>();private ArrayList<Integer> listb = new ArrayList<>();

3.(重点)每次有信息到3000端口就意味着有新的客户端被开启或被关闭,此时需要将其add进好友列表lista和listb,再将更新后的好友列表以 “ip:端口,ip:端口” 字符串形式发送到所有的客户端(关闭的这里自由发挥哈,可以加个判断);

             //包装好友列表String str = "";for(int i=0;i<lista.size();i++) {str+=lista.get(i)+":"+listb.get(i);if(i!=lista.size()-1)str+=",";}text.append(dp.getAddress().getHostAddress()+":"+dp.getPort()+"\n");//将消息发送到所有用户for(Integer i:listb) {DatagramPacket info = new DatagramPacket(str.getBytes(),0,str.getBytes().length,InetAddress.getLocalHost(),i);ds.send(info);}

4.(后记)由于是udp实现,服务端无法知道另一方是否仍在线,所以这里可以设置多一个消息判断,当客户端退出时,发送不同级别的消息给服务端,服务端再将好友列表更新(这里可以自己发挥哈)

客户端:
1.(重点)刚创建一个客户端时先向3000端口发送自己的ip和端口信息,以加入服务端的列表;

String myinfo = "";
DatagramPacket dp = new DatagramPacket(myinfo.getBytes(),0,myinfo.getBytes().length,InetAddress.getLocalHost(),3000);
ds.send(dp);

2.客户端这里也有自己的好友列表,以方便进行展示,有了好友列表后,每次通信都是点到点的,需要用户自己选择聊天对象(默认是好友列表第一个);

3.当消息源为3000端口时,需要将消息按好友列表以 ip:端口,ip:端口 的格式解析,再更新自己的好友列表;否则,将消息和消息源显示至窗口;
4.客户端分配端口的办法是随机的:

 //定义搜寻可用端口上下界private int MIN = 10000;private int MAX = 65000;for(int i=MIN;i<=MAX;i++) {try {ds = new DatagramSocket(i);listb.add(i);lista.add(InetAddress.getLocalHost().getHostAddress());break;}catch(Exception e) {continue;}

5.额外说明,这里需要先启动服务端,再开启客户端;实现通信则需要两个以上的客户端

 //判断是否为服务器发送的消息if(dp1.getPort()==3000) {String[] s = str.split(",");//获得好友数据表for(String i:s) {if(i=="")break;String ss = (i.split("\\:")[1]).substring(0,5);if(listb.contains(Integer.parseInt(ss))){//当端口已存在时continue;}lista.add(InetAddress.getLocalHost().getHostAddress());listb.add((Integer.parseInt(ss)));   }String[] c = new String[6];for(int i=1;i<(lista.size());i++) {c[i-1] = lista.get(i)+":"+listb.get(i);}list.setListData(c);System.out.print(InetAddress.getLocalHost()+":");}else {textr.append(dp1.getAddress().getHostAddress()+":"+dp1.getPort()+"说:"+new String(dp1.getData(),0,dp1.getLength())+"\n");}

服务端和客户端之间的交流:

源代码:

//服务端
package com.ui.udp;import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.TextArea;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;import javax.sound.sampled.Port;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;//服务器端
public class UDPServer extends JFrame{private ArrayList<String> lista = new ArrayList<>();private ArrayList<Integer> listb = new ArrayList<>();private TextArea text=null;public static void main(String[] args){UDPServer server = new UDPServer();server.init();server.udp();}public void init() {setSize(500,500);setResizable(false);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setTitle("Socket聊天室服务器端");setLayout(new BorderLayout());JPanel panel1 = new JPanel(new FlowLayout(FlowLayout.RIGHT));JLabel l1 = new JLabel("开始监听3000端口!");panel1.add(l1);add(panel1,BorderLayout.NORTH);JPanel l2 = new JPanel();JButton exit = new JButton("退出");l2.add(exit);add(l2,BorderLayout.SOUTH);JPanel l3 = new JPanel();text = new TextArea(10,50);text.setEditable(false);l3.add(text);l3.setBorder(BorderFactory.createTitledBorder("用户列表"));add(l3,BorderLayout.SOUTH);setVisible(true);}public void udp() {DatagramSocket ds=null;try {ds = new DatagramSocket(null);ds.bind(new InetSocketAddress(3000));byte[] buf = new byte[1024];DatagramPacket dp = new DatagramPacket(buf,buf.length);while(true) {ds.receive(dp);if(!listb.contains(dp.getPort())) {lista.add(dp.getAddress().getHostAddress());listb.add(dp.getPort());String str = "";for(int i=0;i<lista.size();i++) {str+=lista.get(i)+":"+listb.get(i);if(i!=lista.size()-1)str+=",";}text.append(dp.getAddress().getHostAddress()+":"+dp.getPort()+"\n");for(Integer i:listb) {DatagramPacket info = new DatagramPacket(str.getBytes(),0,str.getBytes().length,InetAddress.getLocalHost(),i);ds.send(info);}}}}catch(Exception e) {e.printStackTrace();}finally {ds.close();}}
}
//客户端
package com.ui.udp;import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Scanner;import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;public class UDPClient extends JFrame{public static void main(String[] args) {UDPClient client = new UDPClient();client.init();client.udp();
}private JPanel panel1 = new JPanel(new FlowLayout(FlowLayout.RIGHT));private JLabel l1 = new JLabel("开始监听3000端口!");private JPanel panel2 = new JPanel(new FlowLayout(FlowLayout.LEFT));private TextArea textr = new TextArea(10,40);private TextArea texts = new TextArea(5,78);private JPanel panell = new JPanel();private JPanel panelr = new JPanel();private JPanel panels = new JPanel();private JButton btn1 = new JButton("发送");private JButton btn2 = new JButton("清空");private JPanel panel3 = new JPanel();//建立好友列表缓冲private ArrayList<String> lista = new ArrayList<>();private ArrayList<Integer> listb = new ArrayList<>();//定义搜寻可用端口上下界private int MIN = 10000;private int MAX = 65000;private DatagramSocket ds=null;private int index=0;//设置好友选择JList<String> list = new JList<>();public void init() {setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setSize(605,450);setResizable(false);setTitle("Socket聊天室服务器端");setLayout(new BorderLayout());panel1.add(l1);add(panel1,BorderLayout.NORTH);//存放中间部分panell.setBorder(BorderFactory.createTitledBorder("好友列表"));panell.setPreferredSize(new Dimension(250,200));panell.setBackground(new Color(255,255,255));panell.add(list);textr.setEditable(false);panelr.setBorder(BorderFactory.createTitledBorder("聊天记录"));panelr.add(textr);texts.setEditable(true);panels.setBorder(BorderFactory.createTitledBorder("请输入文字"));panels.add(texts);panel2.add(panell);panel2.add(panelr);panel2.add(panels);add(panel2,BorderLayout.CENTER);panel3.add(btn1);panel3.add(btn2);add(panel3,BorderLayout.SOUTH);btn1.addActionListener(new ActionListener() {//确认键@Overridepublic void actionPerformed(ActionEvent e) {try {send();textr.append("我对"+InetAddress.getLocalHost().getHostAddress()+":"+(int)(listb.get(index+1))+"说:"+texts.getText()+"\n");texts.setText("");} catch (Exception e1) {e1.printStackTrace();}}});list.addListSelectionListener(new ListSelectionListener() {@Overridepublic void valueChanged(ListSelectionEvent e) {index = list.getLeadSelectionIndex();}});//清空编辑btn2.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {texts.setText("");}});setVisible(true);}//为好友发送数据public void send() throws Exception {String str = texts.getText();DatagramPacket pds = new DatagramPacket(str.getBytes(),0,str.getBytes().length,InetAddress.getLocalHost(),(int)(listb.get(index+1)));ds.send(pds);}public void udp(){try {for(int i=MIN;i<=MAX;i++) {try {ds = new DatagramSocket(i);listb.add(i);lista.add(InetAddress.getLocalHost().getHostAddress());break;}catch(Exception e) {continue;}}//发送空数据,到服务器报道byte[] buf = new byte[1024];byte[] buf1 = new byte[1024];String myinfo = "";DatagramPacket dp = new DatagramPacket(myinfo.getBytes(),0,myinfo.getBytes().length,InetAddress.getLocalHost(),3000);ds.send(dp);//接受服务端的好友列表DatagramPacket dp1 = new DatagramPacket(buf,buf.length);while(true) {ds.receive(dp1);String str = new String(dp1.getData());byte[] a = new byte[4];//判断是否为服务器发送的消息if(dp1.getPort()==3000) {String[] s = str.split(",");//获得好友数据表for(String i:s) {if(i=="")break;String ss = (i.split("\\:")[1]).substring(0,5);if(listb.contains(Integer.parseInt(ss))){//当端口已存在时continue;}lista.add(InetAddress.getLocalHost().getHostAddress());listb.add((Integer.parseInt(ss)));    }String[] c = new String[6];for(int i=1;i<(lista.size());i++) {c[i-1] = lista.get(i)+":"+listb.get(i);}list.setListData(c);System.out.print(InetAddress.getLocalHost()+":");}else {textr.append(dp1.getAddress().getHostAddress()+":"+dp1.getPort()+"说:"+new String(dp1.getData(),0,dp1.getLength())+"\n");}}}catch(Exception e) {e.printStackTrace();}finally {ds.close();}}
}

【UDP实现聊天室(附带源码)】eclipse平台相关推荐

  1. PHP匿名在线聊天室系统源码 自适应PC+WAP端

    介绍: PHP匿名在线聊天室系统源码 自适应PC+WAP端 可发语音.图片 修改数据库config\settings.php可拿去搭建专门跟客户聊天的网站 网盘下载地址: http://kekewl. ...

  2. PHP匿名在线聊天室系统源码

    PHP匿名在线聊天室系统源码,自适应PC+WAP端,可发 语音.图片.带有三套主题模板,完美可用. [完整源码链接] PHP匿名在线聊天室系统源码.zip-PHP文档类资源-CSDN文库

  3. 聊聊语音聊天室app源码实时音视频中的技术难点:回声消除+噪声消除

    聊聊语音聊天室app源码实时音视频中的技术难点:回声消除+噪声消除 在聊聊语音聊天室app源码各个实时音视频互动场景中,回声和噪声对于影响用户体验而言都是很大的问题.音视频正在发展成为互联网线上沟通的 ...

  4. 分享66个PHP聊天室类源码,总有一款适合您

    分享66个PHP聊天室类源码,总有一款适合您 66个PHP聊天室类源码下载链接:https://pan.baidu.com/s/1_Fbbc3WMVWN7jjgTRaCnXw?pwd=h75j 提取码 ...

  5. Anlin-chat多功能聊天室php源码下载,极速安装

    一.名称:Anlin-chat多功能聊天室php源码 二.简介(作用): 可修改成 网站客服系校园站 统 可盈利,利用打赏.VIP.内容付费.广告盈利.资源付费等方法盈利. 三.下载地址: 聊天室zi ...

  6. Java聊天室程序源码 Java即时通讯代码 Java局域网聊天系统 Java即时通讯 Java聊天系统

    Java聊天室程序源码 Java即时通讯代码 Java局域网聊天系统  Java即时通讯 Java聊天系统 public Swingtest002() {// 设置标题setTitle("请 ...

  7. 聊天室软件源码开发中,该如何实现多线程同步?

    问题背景 在聊天室软件源码开发中,需执行多线程任务:任务1.任务2并行执行:等全部执行完成后,执行任务3. // 每个 任务 通过 sleep 模拟耗时 val task1: () -> Str ...

  8. 聊天室软件源码前端性能优化,缓存角度的相关分析

    在我们考虑提高聊天室软件源码页面渲染速度之前先来思考一个问题,一个页面的速度由什么决定?显而易见,这里主要包含两方面的影响因素. 1.资源传输时间(tcp链接时间和响应时间) 2.dom渲染时间 这两 ...

  9. 实现一个简单的语音聊天室(源码)

    语音聊天室,或多人语音聊天,是即时通信应用中常见的功能之一,比如,QQ的语音讨论组就是我们用得比较多的. 这篇文章将实现一个简单的语音聊天室,让多个人可以进入同一个房间进行语音沟通.先看运行效果截图: ...

  10. 实现一个简单的视频聊天室(源码)

    在 <实现一个简单的语音聊天室>一文发布后,很多朋友建议我也实现一个视频聊天室给他们参考一下,其实,视频聊天室与语音聊天室的原理是差不多的,由于加入了摄像头.视频的处理,逻辑会繁杂一些,本 ...

最新文章

  1. 制胜人工智能时代——企业人工智能应用现状分析(第三版)
  2. 3分钟解决MySQL 1032 主从错误(转)
  3. cheerio api
  4. 广西大学计算机英语复试的内容,广西大学计算机专业的研究生复试时
  5. C语言小知识---奇葩的小数
  6. Qt学习之路_008-最全的Qt学习总结(前期)
  7. 华为桌面云解决方案概述_解决方案概述和数据安全建议
  8. 点云配准(三) 传统点云配准算法概述
  9. 【SpringBoot系列】自动装配原理
  10. BZOJ2434[Noi2011]阿狸的打字机——AC自动机+dfs序+树状数组
  11. 模仿6ecc 主页 主体部分(查看附件点击6eccHTML 就会看到如下页面效果)
  12. 红孩儿编辑器的开发规范
  13. 从零搭建Spring Boot脚手架:手写Mybatis通用Mapper4
  14. win10系统编辑服务器在哪个文件夹,文件夹选项在哪里,小编教你Win10文件夹选项在哪...
  15. Python文本分析-常用中文停用词表(Chinese Stop Words)
  16. 帆软报表制作过程的小知识
  17. clickhouse连接Tableau
  18. 仿知音漫画网站源码 PC+手机端 帝国cms7.5内核
  19. 大学纠结选择计算机专业or软件专业,却不知道选择是否正确!怎么判断?
  20. java写一个登录系统_用java写一个用户登陆界面

热门文章

  1. vue中子组件和子组件之间怎么通信_Vue组件间通信6种方式
  2. IOS 中微信 网页授权报 key[也就是code]失效 解决办法
  3. 在数据库录入词典数据时,如何自动生成uuid
  4. 农场乐翻天服务器维护,农场乐翻天游戏-农场乐翻天游戏预约v1.0-游戏宝手游网...
  5. Buffer对象中常用的几个方法
  6. 这可能是全网Spring Cloud Gateway限流最完整的方案了!
  7. oracle函数fun_get,oracle的函数
  8. 淘淘商城第96讲——单点登录之用户登录
  9. 期待你能成为孩子们的“全能超人”
  10. C# 3DES 加密