1程序流程
1.1用户登录
客户端:
1、发送登录信息:LOGIN|Username
处理USERLISTS命令:所有在线用户的用户名 ---(新客户端)
2、处理新上线用户信息:ADD|username---(已在线客户端)
服务器端:
1、得到所有在线用户信息名称,发回给客户端:USERLISTS|user1_user2_user3
2、将当前登录用户的信息(用户名),发送给已经在线的其他用户:ADD|userName
3、将当前登录的Socket信息放入Arraylist中
1.2私聊
客户端:
1、选择用户
2、组织一个交互协议,发送到服务器:MSG|SenderName|RecName|MSGInfo
3、接收服务器转发回的消息
服务器端:
1、解析MSG消息协议字符串,通过RecName用户名查找,找到目标ServertChat
2、向目标对象发送消息:MSG|SenderName|MSGInfo
1.3 群聊
MSG|Sendername|ALL|MSGInfo
1.4 用户退出连接(待全部实现)
客户端:
1、向服务器发送下线消息:OFFLINE|username
2、清空在线用户列表
3、处理下线用户信息:DEL|username
删除用户列表中的username
服务器端:
1、处理OFFLINE,向所有的其他在线用户发送用户下线消息:DEL|username
2、清除ArrayList中的当前用户信息(ServerChat)
1.5 服务器关闭
客户端:
1、处理CLOSE命令:界面显示服务器关闭
2、关闭ClientChat
3、清空在线用户列表
服务器端:
1、向所有在线用户发送关闭服务器的信息:CLOSE
2、遍历Arraylist将其中的每一个ServerChat关闭
3、ArrayList要清空
4、关闭ServerListener
5、关闭ServerSocket
代码实现
客户端
package Client;
import java.io.*;
import java.net.*;
public class ClientChat extends Thread {
BufferedReader br=null;
PrintWriter pw=null;
Socket socket=null;
public ClientChat(Socket socket,String sName) {
super(sName);
this.socket=socket;
}
public void run() {
try {
br=new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
pw=new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8")));
String sLogin="LOGIN|"+this.getName();
sendMsg(sLogin);
String str="";
while((str=br.readLine())!=null){
String [] commands=str.split("\\|");
if(commands[0].equals("USERLISTS")){
String sUSers=commands[1];
String [] onlineusers=sUSers.split("\\_");
ClientMG.getclientMG().addItems(onlineusers);
}
else if(commands[0].equals("ADD")){
String sNewUser=commands[1];
ClientMG.getclientMG().addItem(sNewUser);
}
else if(commands[0].equals("MSG")){
String sendName=commands[1];
String MsgInfo=commands[2];
ClientMG.getclientMG().setLogTxt("["+sendName+"]:");
ClientMG.getclientMG().setLogTxt(MsgInfo);
}
}
} catch (IOException e) {
e.printStackTrace();
}
finally {
try {
if(pw!=null)
pw.close();
if(br!=null)
br.close();
if(socket!=null)
socket.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
public void sendMsg(String str){
pw.println(str);
pw.flush();
}
}
package Client;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.awt.event.ActionEvent;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import javax.swing.JList;
public class ClientForm extends JFrame {
private JPanel contentPane;
public JPanel panel;
public JLabel lblIp;
public JTextField textIP;
public JLabel label;
public JTextField textPort;
public JButton btnLogin;
public JButton btnClose;
public JPanel panel_1;
public JTextArea textSend;
public JButton btnSend;
DefaultListModel<String> itemUsers;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
ClientForm frame = new ClientForm();
frame.setVisible(true);
ClientMG.getclientMG().setClientForm(frame);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public ClientForm() {
setTitle("\u5BA2\u6237\u7AEF");
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 514, 608);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
panel = new JPanel();
panel.setBorder(new TitledBorder(null, "\u914D\u7F6E\u4FE1\u606F", TitledBorder.LEADING, TitledBorder.TOP, null, null));
panel.setBounds(10, 10, 488, 67);
contentPane.add(panel);
panel.setLayout(null);
lblIp = new JLabel("IP");
lblIp.setBounds(10, 31, 54, 15);
panel.add(lblIp);
textIP = new JTextField();
textIP.setText("输入主机IP");
textIP.setBounds(34, 28, 102, 21);
panel.add(textIP);
textIP.setColumns(10);
label = new JLabel("\u7AEF\u53E3");
label.setBounds(146, 31, 54, 15);
panel.add(label);
textPort = new JTextField();
textPort.setText("60000");
textPort.setBounds(178, 28, 45, 21);
panel.add(textPort);
textPort.setColumns(10);
btnLogin = new JButton("\u767B\u5F55");
btnLogin.addActionListener(new BtnLoginActionListener());
btnLogin.setBounds(345, 27, 68, 23);
panel.add(btnLogin);
btnClose = new JButton("\u5173\u95ED");
btnClose.addActionListener(new BtnCloseActionListener());
btnClose.setBounds(410, 27, 68, 23);
panel.add(btnClose);
label_2 = new JLabel("\u7528\u6237\u540D");
label_2.setBounds(229, 31, 54, 15);
panel.add(label_2);
textUser = new JTextField();
textUser.setBounds(269, 28, 66, 21);
panel.add(textUser);
textUser.setColumns(10);
panel_1 = new JPanel();
panel_1.setBorder(new TitledBorder(null, "\u64CD\u4F5C", TitledBorder.LEADING, TitledBorder.TOP, null, null));
panel_1.setBounds(10, 462, 488, 108);
contentPane.add(panel_1);
panel_1.setLayout(null);
btnSend = new JButton("\u53D1\u9001");
btnSend.addActionListener(new BtnSendActionListener());
btnSend.setBounds(407, 75, 71, 23);
panel_1.add(btnSend);
btnSendAll = new JButton("\u7FA4\u53D1");
btnSendAll.addActionListener(new BtnSendAllActionListener());
btnSendAll.setBounds(336, 75, 65, 23);
panel_1.add(btnSendAll);
scrollPane_2 = new JScrollPane();
scrollPane_2.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane_2.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane_2.setBounds(10, 24, 468, 42);
panel_1.add(scrollPane_2);
textSend = new JTextArea();
textSend.setLineWrap(true);
scrollPane_2.setViewportView(textSend);
textSend.setColumns(10);
scrollPane = new JScrollPane();
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setBorder(new TitledBorder(null, "\u804A\u5929\u8BB0\u5F55", TitledBorder.LEADING, TitledBorder.TOP, null, null));
scrollPane.setBounds(10, 87, 286, 378);
contentPane.add(scrollPane);
textLog = new JTextArea();
textLog.setLineWrap(true);
scrollPane.setViewportView(textLog);
scrollPane_1 = new JScrollPane();
scrollPane_1.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane_1.setBorder(new TitledBorder(null, "\u5728\u7EBF\u7528\u6237", TitledBorder.LEADING, TitledBorder.TOP, null, null));
scrollPane_1.setBounds(297, 87, 201, 378);
contentPane.add(scrollPane_1);
itemUsers=new DefaultListModel<String>();
listUsers = new JList(itemUsers);
scrollPane_1.setViewportView(listUsers);
}
public JLabel label_2;
public JTextField textUser;
public JScrollPane scrollPane;
public JTextArea textLog;
public JScrollPane scrollPane_1;
public JList listUsers;
public JButton btnSendAll;
public JScrollPane scrollPane_2;
private class BtnLoginActionListener implements ActionListener {
public void actionPerformed(ActionEvent arg0) {
String IP=textIP.getText().trim();
int port=Integer.parseInt(textPort.getText().trim());
if(ClientMG.getclientMG().Connect(IP, port, textUser.getText().trim())){
ClientMG.getclientMG().setLogTxt("已登录到服务器。");
}
else{
ClientMG.getclientMG().setLogTxt("登录服务器失败!");
}
}
}
private class BtnSendActionListener implements ActionListener {
public void actionPerformed(ActionEvent arg0) {
if(listUsers.getSelectedIndex()>=0){
String sendName=ClientMG.getclientMG().getClientChat().getName();
String RecName=listUsers.getSelectedValue().toString();
String MSGInfo=textSend.getText().trim();
String MSG="MSG|"+sendName+"|"+RecName+"|"+MSGInfo;
ClientMG.getclientMG().getClientChat().sendMsg(MSG);
ClientMG.getclientMG().setLogTxt("[我]:");
ClientMG.getclientMG().setLogTxt(MSGInfo);
textSend.setText("");
}
}
}
private class BtnCloseActionListener implements ActionListener {
public void actionPerformed(ActionEvent arg0) {
}
}
private class BtnSendAllActionListener implements ActionListener {
public void actionPerformed(ActionEvent arg0) {
String sendName=ClientMG.getclientMG().getClientChat().getName();
String RecName="ALL";
String MSGInfo=textSend.getText().trim();
String MSG="MSG|"+sendName+"|"+RecName+"|"+MSGInfo;
ClientMG.getclientMG().getClientChat().sendMsg(MSG);
ClientMG.getclientMG().setLogTxt("[我]:");
ClientMG.getclientMG().setLogTxt(MSGInfo);
textSend.setText("");
}
}
}
package Client;
import java.net.*;
public class ClientMG {
private static final ClientMG clientMG=new ClientMG();
private ClientMG() {}
public static ClientMG getclientMG(){
return clientMG;
}
private ClientForm clientWin;
public void setClientForm(ClientForm c){
clientWin=c;
}
public void setLogTxt(String str){
clientWin.textLog.append(str+"\r\n");
}
ClientChat cChat;
public ClientChat getClientChat(){
return cChat;
}
public boolean Connect(String IP,int port,String uName){
Socket socket=null;
try {
socket=new Socket(IP, port);
cChat=new ClientChat(socket,uName);
cChat.start();
return true;
}catch (Exception e) {
e.printStackTrace();
return false;
}
}
public void addItems(String [] susers){
for(int i=0;i<susers.length;i++){
addItem(susers[i]);
}
}
public void addItem(String sNewUser){
clientWin.itemUsers.addElement(sNewUser);
}
}
服务器端
package Server;
import java.io.*;
import java.net.*;
public class ServerChat extends Thread {
BufferedReader br = null;
PrintWriter pw = null;
Socket socket=null;
public ServerChat(Socket socket) {
this.socket = socket;
}
public void run() {
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8")));
String str ="";
while((str = br.readLine())!=null){
String [] commands=str.split("\\|");
if(commands[0].equals("LOGIN")){
String sUserName=commands[1];
this.setName(sUserName);
ServerMG.getServerMG().getOnlineNames(this);
ServerMG.getServerMG().sendNewUsertoAll(this);;
ServerMG.getServerMG().addOnlielist(this);
}
else if(commands[0].equals("MSG")){
String sendName=commands[1];
String RecName=commands[2];
String MSGInfo=commands[3];
if(RecName.equals("ALL")){
String sRtnMsg="MSG|"+sendName+"|"+MSGInfo;
ServerMG.getServerMG().sendMsgtoAll(sRtnMsg, this);
ServerMG.getServerMG().setLogTxt(sendName+"发消息["+MSGInfo+"]给"+RecName);
}
else{
ServerChat sc=ServerMG.getServerMG().getServerChatByName(RecName);
if(sc!=null){
String sRtnMsg="MSG|"+sendName+"|"+MSGInfo;
sc.sendMsg(sRtnMsg);
ServerMG.getServerMG().setLogTxt(sendName+"发消息["+MSGInfo+"]给"+RecName);
}
}
}
ServerMG.getServerMG().setLogTxt("客户端:"+str);
}
} catch (Exception e) {
e.printStackTrace();
}
finally {
try {
if (pw != null)
pw.close();
if (br != null)
br.close();
if (socket != null)
socket.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
public void sendMsg(String str){
pw.println(str);
pw.flush();
}
}
package Server;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.net.*;
import java.io.*;
public class ServerForm extends JFrame {
private JPanel contentPane;
public JPanel panel;
public JLabel label;
public JTextField textPort;
public JButton btnStart;
public JButton btnEND;
public JScrollPane scrollPane;
public JTextArea textLog;
ServerSocket server = null;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
ServerForm frame = new ServerForm();
frame.setVisible(true);
ServerMG.getServerMG().setServerForm(frame);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public ServerForm() {
setTitle("\u591A\u4EBA\u804A\u5929\u670D\u52A1\u5668");
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 466);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
panel = new JPanel();
panel.setBorder(new TitledBorder(null, "\u914D\u7F6E\u4FE1\u606F", TitledBorder.LEADING, TitledBorder.TOP, null, null));
panel.setBounds(10, 10, 424, 66);
contentPane.add(panel);
panel.setLayout(null);
label = new JLabel("\u7AEF\u53E3\uFF1A");
label.setBounds(24, 31, 54, 15);
panel.add(label);
textPort = new JTextField();
textPort.setText("60000");
textPort.setBounds(62, 28, 66, 21);
panel.add(textPort);
textPort.setColumns(10);
btnStart = new JButton("\u5F00\u542F\u670D\u52A1");
btnStart.addActionListener(new BtnStartActionListener());
btnStart.setBounds(153, 27, 93, 23);
panel.add(btnStart);
btnEND = new JButton("\u5173\u95ED\u670D\u52A1");
btnEND.addActionListener(new BtnENDActionListener());
btnEND.setBounds(256, 27, 93, 23);
panel.add(btnEND);
scrollPane = new JScrollPane();
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setBorder(new TitledBorder(null, "\u6D88\u606F\u8BB0\u5F55", TitledBorder.LEADING, TitledBorder.TOP, null, null));
scrollPane.setBounds(10, 86, 424, 342);
contentPane.add(scrollPane);
textLog = new JTextArea();
textLog.setLineWrap(true);
scrollPane.setViewportView(textLog);
}
private class BtnStartActionListener implements ActionListener {
public void actionPerformed(ActionEvent arg0) {
int port = Integer.parseInt(textPort.getText().trim());
if(ServerMG.getServerMG().CreateServer(port)){
ServerMG.getServerMG().setLogTxt("服务器开启...");
}
else {
ServerMG.getServerMG().setLogTxt("服务器启动失败。");
}
}
}
private class BtnENDActionListener implements ActionListener {
public void actionPerformed(ActionEvent arg0) {
ServerMG.getServerMG().CloseServer();
}
}
}
package Server;
import java.net.*;
public class ServerListener extends Thread {
ServerSocket server=null;
public ServerListener(ServerSocket server) {
this.server=server;
}
public void run() {
Socket socket = null;
try {
while(true){
socket = server.accept();
ServerMG.getServerMG().setLogTxt("客户端信息:" + socket);
new ServerChat(socket).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package Server;
import java.io.IOException;
import java.net.*;
import java.util.ArrayList;
public class ServerMG {
private static final ServerMG servermg=new ServerMG();
private ServerMG() {}
public static ServerMG getServerMG(){
return servermg;
}
private ServerForm serverWin;
public void setServerForm(ServerForm s){
serverWin=s;
}
public void setLogTxt(String str){
serverWin.textLog.append(str+"\r\n");
}
ServerSocket server;
public boolean CreateServer(int port){
try {
server = new ServerSocket(port);
new ServerListener(server).start();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public void CloseServer(){
try {
if(server!=null)
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
ArrayList<ServerChat> alOnlineList=new ArrayList<ServerChat>();
public synchronized void addOnlielist(ServerChat sc){
alOnlineList.add(sc);
}
public void getOnlineNames(ServerChat sc){
if(alOnlineList.size()>0){
String stUser="";
for(int i=0;i<alOnlineList.size();i++){
ServerChat s=alOnlineList.get(i);
stUser+=s.getName()+"_";
}
sc.sendMsg("USERLISTS|"+stUser);
}
}
public void sendNewUsertoAll(ServerChat scurr){
for(int i=0;i<alOnlineList.size();i++){
ServerChat s=alOnlineList.get(i);
s.sendMsg("ADD|"+scurr.getName());
}
}
public ServerChat getServerChatByName(String sname){
for(int i=0;i<alOnlineList.size();i++){
ServerChat s=alOnlineList.get(i);
if(s.getName().equals(sname)){
return s;
}
}
return null;
}
public void sendMsgtoAll(String msg,ServerChat sc){
for(int i=0;i<alOnlineList.size();i++){
ServerChat s=alOnlineList.get(i);
if(!s.equals(sc)){
s.sendMsg(msg);
}
}
}
}
只需要启动ServerForm 和ClientForm 即可运行
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/1e5d20219aba1bc1027c78583eda659e.png)