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