模拟聊天系统

package chatsystem;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.awt.event.WindowListener;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;


import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;//
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
import javax.swing.border.TitledBorder;


/**
 * 聊天窗口
 * 
 *
 */
public class ChatFrame extends JFrame implements ActionListener{
//定义组件
Socket socket;
//jpanel容器
JPanel p1,p2,p3,p4,p5,p6,p7;
//文本域
JTextArea area1,area2;
//滚动容器
JScrollPane js1,js2,js3;
//文本标签
JLabel lab;
//下拉列表
JComboBox box;
//复选框
JCheckBox checkbox;
//文本框
JTextField text;
//按钮
JButton sendBut,refrashBut;
//模型
DefaultListModel model;
JList list;
String name;//zs
String sex;
public void init() {
//定义窗体的特征
//窗体标题
this.setTitle("【"+name+"】进入了聊天室");
//窗体大小
this.setSize(520,570);
//禁用放大按钮
this.setResizable(false);
//窗体位置(居中显示)
this.setLocationRelativeTo(null);
this.pack();//自动适应大小
//窗体关闭
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

public ChatFrame(String name,String sex) {//zs
this.name = name;
this.sex = sex;

System.out.println("sex:"+sex);

p1 = new JPanel();
//设置p1的布局为网格布局
p1.setLayout(new GridLayout(2, 1));
//往p1中添加组件
area1 = new JTextArea(10,10);
//实例化js1滚动容器
js1 = new JScrollPane(area1);
js1.setBorder(new TitledBorder("主聊天频道"));
js1.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
p1.add(js1);

area2 = new JTextArea(10,10);
//实例化js1滚动容器
js2 = new JScrollPane(area2);
js2.setBorder(new TitledBorder("我的频道"));
js2.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
p1.add(js2);

//实例化p2对象
p2 = new JPanel();
p2.setLayout(new FlowLayout(FlowLayout.LEFT));
lab = new JLabel("对");
box = new JComboBox();
box.addItem("所有人");
box.addItem("张三");
checkbox = new JCheckBox("私聊");
//把组件添加到p2
p2.add(lab);
p2.add(box);
p2.add(checkbox);


//实例化p3
p3 = new JPanel();
p3.setLayout(new FlowLayout(FlowLayout.LEFT));
text = new JTextField(30);
sendBut = new JButton("发送>>");
//把组件添加到p3
p3.add(text);
p3.add(sendBut);

//实例化p4
p4 = new JPanel();
p4.setLayout(new GridLayout(2, 1));
p4.add(p2);
p4.add(p3);

//实例化p5
p5 = new JPanel();
p5.setLayout(new BorderLayout());
p5.add(p1,BorderLayout.NORTH);
p5.add(p4,BorderLayout.SOUTH);

//实例化p6
p6 = new JPanel();
p6.setLayout(new BorderLayout());
model = new DefaultListModel();
model.addElement("张三");
model.addElement("李四");
list = new JList(model);

list.setVisibleRowCount(18); //设置行
list.setFixedCellHeight(24); //设置高
list.setFixedCellWidth(50); //设置宽



js3 = new JScrollPane(list);
js3.setBorder(new TitledBorder("好友列表"));
js3.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

refrashBut = new JButton("刷新");

p6.add(js3,BorderLayout.NORTH);
p6.add(refrashBut,BorderLayout.SOUTH);

//实例化p7
p7 = new JPanel();
p7.setLayout(new FlowLayout(FlowLayout.LEFT));
p7.add(p5);
p7.add(p6);

//把p7添加到面板中
this.getContentPane().add(p7);

init();

//窗体是否显示
this.setVisible(true);
//绑定窗体事件
   this.addWindowListener(new WindowAdapter() {


@Override
public void windowClosing(WindowEvent e) {
//super.windowClosing(arg0);
try {
//向服务器发送关闭通知
PrintWriter out=new PrintWriter(socket.getOutputStream());
out.println(ChatUtil.QUIT_CHAT);//发送关闭聊天室的标识码
out.flush();//发送一个信息要刷新一次
out.println("【"+name+"】"+"退出了聊天室");//【xxx】退出聊天室
out.flush();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
   
   });
   //绑定点击事件(发送按钮)
   sendBut.addActionListener(this);
}
//获取客户端的socket
public void getSocket() {
try {
//socket
ClientSocket c = new ClientSocket(this);//this是当前窗体
//往服务端发送信息
socket=c.socket;
PrintWriter out = new PrintWriter(socket.getOutputStream());
//1、发送功能标识码
out.println(ChatUtil.FRIEND_LIST);//1008611//发送列表的标识码
out.flush();
//2、发送登录信息
out.println(this.name+":"+this.sex);//zs:男
out.flush();

out.println(ChatUtil.ENTER_CHAT);//11111,发送进入聊天室的标识码
out.flush();
out.println("【"+this.name+"】"+"进入聊天室");//发送进入聊天室的信息
out.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public static void main(String[] args) {
//主方法没用到,啊哈哈
}
@Override//发送按钮的点击事件处理过程
public void actionPerformed(ActionEvent e) {
try {
PrintWriter out = new PrintWriter(socket.getOutputStream());
if(e.getActionCommand().equals("发送>>")) {//判断点击事件是够是否是 发送按钮(sendBut) 触发的

if(!checkbox.isSelected()) {//如果私聊复选框没有选中,则说明是群聊
String chatContent=text.getText();//读取用户输入的信息
text.setText("");
out.println(ChatUtil.GROUP_CHAT);//发送群聊标识码个服务端
out.flush();//发送一次信息要刷新一次
out.println(name+" :"+chatContent);//发送群聊的信息
out.flush();//刷新

}else if(checkbox.isSelected()){//说明私聊复选框选中了,是私聊
   String PrivateChatContent=text.getText();//私聊的内容
   text.setText("");
   String PrivateName=(String)box.getSelectedItem();//私聊人的名字,格式是 :   姓名(性别)
   out.println(ChatUtil.PRIVATE_CHAT);//发送私聊的标识码给服务端
   out.flush();//发送一次信息要刷新一次
   out.println(name+" :"+PrivateChatContent);//发送私聊的内容给服务端
   out.flush();//刷新
   out.println(PrivateName);//发送到服务端
   out.flush();
}
}
} catch (IOException e1) {
e1.printStackTrace();
}
}

}

------------------------------------------------------------------

package chatsystem;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;


/**
 * 客户端的socket
 *
 *
 */
public class ClientSocket {
public static Socket socket;
ChatFrame chatFrame;//聊天窗体
public ClientSocket(ChatFrame chatFrame) {
this.chatFrame = chatFrame;
try {
socket = new Socket(ChatUtil.ADDRESS, ChatUtil.PORT);

//启动线程
new Thread(new ClientReadWriterThead()).start();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

//定义客户端多线程的读写类来完成对服务端的操作
class ClientReadWriterThead implements Runnable{
BufferedReader read;
public ClientReadWriterThead() {
try {
read = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

@Override
public void run() {
try {
String message = "";
while((message = read.readLine())!=null) {//1、1008611
//好友列表
if(message.equals(ChatUtil.FRIEND_LIST)) {//标识码为好友列表
String loginInfo = read.readLine();//zs(男):ls(女):ww(保存):
//拆分
String[] users = loginInfo.split(":");

//清空model中的元素
chatFrame.model.clear();
//清空下拉列表中的元素
chatFrame.box.removeAllItems();
chatFrame.box.addItem("所有人");
for (int i = 0; i < users.length; i++) {
chatFrame.model.addElement(users[i]);
chatFrame.box.addItem(users[i]);
}

}else if(message.equals(ChatUtil.ENTER_CHAT)) {//标识码为进入聊天室
String loginInfo = read.readLine();//读取进入聊天室的内容
chatFrame.area1.append(loginInfo+"\n");//把其内容加入文本域内

chatFrame.area2.append(loginInfo+"\n");

}else if(message.equals(ChatUtil.QUIT_CHAT)) {//标识码为退出聊天室
String str=read.readLine();//退出聊天室的内容
chatFrame.area1.append(str+"\n");//把其内容添加到文本域内
chatFrame.area2.append(str+"\n");

}else if(message.equals(ChatUtil.GROUP_CHAT)) {
String str1=read.readLine();//群聊 的内容
chatFrame.area1.append(str1+"\n");//把其内容添加到文本域内
//chatFrame.area2.append(str1+"\n");

}else if(message.equals(ChatUtil.PRIVATE_CHAT)) {
String PrivateChatContent=read.readLine();//私聊的内容
//chatFrame.area1.append(PrivateChatContent+"\n");//把其内容添加到文本域内
chatFrame.area2.append(PrivateChatContent+"\n");
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}


}

}

-----------------------------------------------------------------------

package chatsystem;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;


import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;


/**
 * 聊天系统的登录界面
 *
 *
 */
public class LoginFrame extends JFrame implements ActionListener{
//定义组件
JLabel userLab,addrLab,portLab;//标签
JTextField userText,addrText,portText;//文本框
JRadioButton radioMan,radioWoman,radioser;//单选按钮
ButtonGroup group ;//组
JButton connectBut,closeBut;//按钮
//容器
JPanel p1,p2,p3;

public LoginFrame(){
//实例化组件
p1 = new JPanel();
p1.setLayout(new FlowLayout(FlowLayout.LEFT));

userLab = new JLabel("姓名:");
userText = new JTextField(10);
radioMan = new JRadioButton("男");
radioMan.setSelected(true);
radioWoman = new JRadioButton("女");
radioser = new JRadioButton("保密"); 
//把单选按钮,添加到组中
group = new ButtonGroup();
group.add(radioMan);
group.add(radioWoman);
group.add(radioser);

//往p1中,添加组件了(注意:组不需要添加到容器中)
p1.add(userLab);
p1.add(userText);
p1.add(radioMan);
p1.add(radioWoman);
p1.add(radioser);


p2 = new JPanel();
p2.setLayout(new FlowLayout(FlowLayout.LEFT));
addrLab = new JLabel("地址:");

addrText = new JTextField(10);
addrText.setText(ChatUtil.ADDRESS);

portLab = new JLabel("端口:");
portText = new JTextField(10);
portText.setText(ChatUtil.PORT+"");

//把组件添加到p2中
p2.add(addrLab);
p2.add(addrText);
p2.add(portLab);
p2.add(portText);


p3 = new JPanel();
p3.setLayout(new FlowLayout(FlowLayout.CENTER));

connectBut =new JButton("连接");
//绑定事件【点击事件】
connectBut.addActionListener(this);

closeBut = new JButton("断开");
//把组件添加到p3中
p3.add(connectBut);
p3.add(closeBut);





//设置面板的布局模式(流式布局)
this.getContentPane().setLayout(new GridLayout(3,1));//网格布局

//把组件添加到面板了
//1、获取面板
Container c =  this.getContentPane();
//把p1容器添加到面板
c.add(p1);
//把p2容器添加到面板
c.add(p2);
//把p3容器添加到面板
c.add(p3);

init();
}
/**
* 初始化窗体的基本信息
*/
public void init(){
//1、标题
this.setTitle("登录界面");
//2、大小
this.setSize(350,200);
//3、关闭放大功能
this.setResizable(false);
//4、位置
this.setLocationRelativeTo(null);
//5、是否显示
this.setVisible(true);
//6、关闭
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}


//点击事件的处理过程
@Override
public void actionPerformed(ActionEvent e) {
//处理选择中的性别
String sex = "";
if(radioWoman.isSelected()) {
sex = "女";
}else if(radioMan.isSelected()) {
sex = "男";
}else {
sex = "保密";
}
System.out.println("============");
//1、隐藏当前的界面【登录界面】
this.setVisible(false);
//2、显示聊天的界面
ChatFrame c = new ChatFrame(userText.getText(),sex);//登录名,性别传递过来
c.getSocket();
}
public static void main(String[] args) {
new LoginFrame();
}

}

---------------------------------------------------------------

package chatsystem;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;


/**
 * 服务端类
 * 
 */


public class Server {
 
//1、定义用来保存所有用户的集合对象
List<User> userList = new ArrayList<User>();
//2、定义用来保存所有用户打印流对象
List<PrintWriter> printList = new ArrayList<PrintWriter>();

//广播信息(群发)
public void sendMessage(String msg) {//msg:发送的内容
for (int i = 0; i < printList.size(); i++) {
PrintWriter out =  printList.get(i);
out.println(msg);
out.flush();
}
}

public Server() {
try {
ServerSocket ss = new ServerSocket(ChatUtil.PORT);
int count = 0;
while (true) {
System.out.println("等待客户端连接.......");
Socket socket = ss.accept();//zs
//把用户对应的打印流保存起来
printList.add(new PrintWriter(socket.getOutputStream()));
count++;
System.out.println("目前有"+count+"个客户端进入了聊天室");
//开启线程
new Thread(new ServerReadWriterThread(socket)).start();
}

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//定义线程内部类来处理读写操作
class ServerReadWriterThread implements Runnable{
BufferedReader read;
Socket socket;
public ServerReadWriterThread(Socket socket) {
try {
this.socket = socket;
read = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
public void run() {
try {
/**
* 客户端给服务端发送了两条信息
* 1、发送功能标识码   1008611
* 2、发送登录信息 zs:男
*/
String message = "";
while((message = read.readLine())!=null) {// 1008611

if(message.equals(ChatUtil.FRIEND_LIST)) {//好友列表的标识码
String userinfo = read.readLine();//读取发送过来的信息是按   姓名:性别    格式的

String[] users = userinfo.split(":");//拆分,包装到用户对象上
User user = new User(users[0],users[1],socket);//是一个用户的信息

userList.add(user);//然后再把用户对象添加到用户集合中

String msg = "";
//拼接 zs(男):ls(女):ww(保存):
for (int i = 0; i < userList.size(); i++) {
User u = userList.get(i);
msg += u.getName()+"("+u.getSex()+"):";
}

//把拼接好的内容发送到客户端去做显示
sendMessage(ChatUtil.FRIEND_LIST);//1、1008611,广播,群发
sendMessage(msg);//2、zs(男):ls(女):ww(保存):

}else if(message.equals(ChatUtil.ENTER_CHAT)) {//标识码为进入聊天室
String str = read.readLine();//读取进入聊天室的信息
sendMessage(ChatUtil.ENTER_CHAT);
sendMessage(str);

}else if(message.equals(ChatUtil.QUIT_CHAT)) {//标识码为退出聊天室
String str=read.readLine();//读取退出聊天室的信息
sendMessage(ChatUtil.QUIT_CHAT);//广播,群发
sendMessage(str);

String name=str.substring(1,str.indexOf("】"));//找到退出人的名字,退出信息是按【姓名】格式发送过来的
for (int i = 0; i < userList.size(); i++) {//从集合中循坏找到退出人的名字
User u=userList.get(i);
if(name.equals(u.getName())) {//找到要退出的人的名字
userList.remove(u);//将其从userList集合中移除
break;//退出循坏
}
}
                             //往客户端回传数据(1.功能标识,2.最新的好友列表)
String names="";
for (int i = 0; i < userList.size(); i++) {
User u = userList.get(i);
names += u.getName()+"("+u.getSex()+"):";//拼接,按   (姓名):  格式拼接
}
sendMessage(ChatUtil.FRIEND_LIST);//好友列表标识码,更新好友列表
sendMessage(names);//最新的好友列表拼接的内容

}else if(message.equals(ChatUtil.GROUP_CHAT)) {//标识码为群聊
String str=read.readLine();//群聊的内容
sendMessage(ChatUtil.GROUP_CHAT);//群聊的标识码
sendMessage(str);//群发群聊的内容

}else if(message.equals(ChatUtil.PRIVATE_CHAT)) {//标识码为私聊
String PrivateChatContent=read.readLine();//私聊的内容
String PrivateName=read.readLine();//私聊的人的名字,格式为: 姓名(性别);
String PrivateRealName=PrivateName.substring(0,PrivateName.indexOf("("));//名字
for (int i = 0; i < userList.size(); i++) {//循坏从userList找私聊人的名字
User u=userList.get(i);
if(PrivateRealName.equals(u.getName())) {//找到私聊的人的名字
PrintWriter out=new PrintWriter(u.getSocket().getOutputStream());//私聊人的 输出流对象
out.println(ChatUtil.PRIVATE_CHAT);//私聊的标识码给客户端
out.flush();
out.println(PrivateChatContent);//发送私聊的内容给客户端
out.flush();

if(!u.getSocket().equals(socket)) {//如果不是对自己私聊
PrintWriter out1=new PrintWriter(socket.getOutputStream());
out1.println(ChatUtil.PRIVATE_CHAT);//私聊的标识码
out1.flush();
out1.println(PrivateChatContent);//私聊的内容
out1.flush();
}
break;//找到了就退出循坏
}
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

public static void main(String[] args) {
new Server();
}

}

-------------------------------------------------------------------

package chatsystem;


public final class ChatUtil {
   //地址
public static final String ADDRESS = "localhost";
//端口
public static final int PORT = 9999;
//好友列表标识码
public static final String FRIEND_LIST = "1008611";
//进入聊天室标识码
public static final String ENTER_CHAT="11111";
//退出聊天室标识码
public static final String QUIT_CHAT="22222";
//群聊标识码
public static final String GROUP_CHAT="33333";
//私聊标识码
public static final String PRIVATE_CHAT="44444";

}

----------------------------------------------------------------------------

package chatsystem;
import java.net.Socket;
public class User {
private String name;
private String sex;
private Socket socket;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Socket getSocket() {
return socket;
}
public void setSocket(Socket socket) {
this.socket = socket;
}
public User() {
super();
// TODO Auto-generated constructor stub
}
public User(String name, String sex, Socket socket) {
super();
this.name = name;
this.sex = sex;
this.socket = socket;
}

}

先启动服务端,在启动客户端登录









猜你喜欢

转载自blog.csdn.net/weixin_42044486/article/details/80240738
今日推荐