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

要求:
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() {
//确认键
			@Override
			public 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() {
			@Override
			public void valueChanged(ListSelectionEvent e) {
				index = list.getLeadSelectionIndex();
			}
			
		});
		//清空编辑
		btn2.addActionListener(new ActionListener() {
			@Override
			public 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();
	}
	}
}
  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值