java實現多人聊天室,【UDP實現聊天室(附帶源碼)】eclipse平臺

 2023-12-06 阅读 25 评论 0

摘要:要求: udp實現聊天室,要求服務端只負責好友列表的刷新,不負責消息的轉發 服務端: 1.服務端監聽的是3000端口,其他用戶統一對3000進行監聽,實現實時的好友列表更新; 2.好友列表list和listb分別存放客戶端的ip地址和端口ÿ

要求:
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);}

java實現多人聊天室。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");}

javaweb實現網頁聊天、服務端和客戶端之間的交流:
在這里插入圖片描述
源代碼:

//服務端
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();}}
}

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://808629.com/191069.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 86后生记录生活 Inc. 保留所有权利。

底部版权信息