1,好友聊天模式
1.1,简介
思想:服务器开启ServerSocket等待客户端连接,获取双方的输入输出流,之后进入while循环,不断的接收来自客户端的消息(消息由客户端发送到内存,服务器从内存中获取信息,每次获取完,服务器处于等待状态,类似于消费者等待生产者,处于while中。)客户端同样等待服务器发送的消息,通过Button按钮发送到内存消息。
流程图:
效果图:
1.2,界面代码
服务器端代码
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class qqinpage extends JFrame {
private JLabel ipLabel, userLabel, serverLabel, meanLabel;
private JButton inButton, outButton;
private JTextField userField, serverField;
private JRadioButton meanButton, mean2Button;
private JPanel ipPanel, userPanel, serverPanel, meanPanel, lastPanel;
private JPasswordField ipField;
public qqinpage() {
userLabel = new JLabel("请 输 入 管 理 员 用 户 名:");
ipLabel = new JLabel("请 输 入 管 理 员 密 码:");
serverLabel = new JLabel("请输入你 要开放的 端 口:");
meanLabel = new JLabel("聊 天 方 式:");
inButton = new JButton("开启服务器");
outButton = new JButton("退出");
meanButton = new JRadioButton("双人");
mean2Button = new JRadioButton("多人");
ButtonGroup bg = new ButtonGroup();
bg.add(meanButton);
bg.add(mean2Button);
meanButton.setSelected(true);
ipField = new JPasswordField(20);
userField = new JTextField(20);
serverField = new JTextField(20);
userPanel = new JPanel(new FlowLayout());
serverPanel = new JPanel(new FlowLayout());
meanPanel = new JPanel(new FlowLayout());
lastPanel = new JPanel(new FlowLayout());
ipPanel = new JPanel(new FlowLayout());
userPanel.add(userLabel);
userPanel.add(userField);
serverPanel.add(serverLabel);
serverPanel.add(serverField);
meanPanel.add(meanLabel);
meanPanel.add(meanButton);
meanPanel.add(mean2Button);
lastPanel.add(inButton);
lastPanel.add(outButton);
ipPanel.add(ipLabel);
ipPanel.add(ipField);
addListener();
Container container = getContentPane();
container.setLayout(new GridLayout(5, 1));
container.add(userPanel);
container.add(ipPanel);
container.add(serverPanel);
container.add(meanPanel);
container.add(lastPanel);
setBounds(600, 200, 500, 250);
setTitle("管理员登录");
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void addListener() {
outButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
inButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (userField.getText().equals("")) {
JOptionPane.showMessageDialog(null, "请输入用户名", "提示", JOptionPane.INFORMATION_MESSAGE);
} else if (ipField.getText().equals("")) {
JOptionPane.showMessageDialog(null, "请输入用户名", "提示", JOptionPane.INFORMATION_MESSAGE);
} else if (!meanButton.isSelected() && !mean2Button.isSelected()) {
JOptionPane.showMessageDialog(null, "请选择聊天方式", "提示", JOptionPane.INFORMATION_MESSAGE);
} else if (userField.getText().equals("root") && ipField.getText().equals("123456")) {
if (mean2Button.isSelected()) {
dispose();
new Server(Integer.parseInt(serverField.getText()));
} else {
dispose();
JOptionPane.showMessageDialog(null, "服务器已打开", "提示", JOptionPane.INFORMATION_MESSAGE);
new ServerTPC(Integer.parseInt(serverField.getText()));
}
} else {
JOptionPane.showMessageDialog(null, "密码错误\n程序退出", "提示", JOptionPane.INFORMATION_MESSAGE);
System.exit(1);
}
}
});
}
public static void main(String[] args) {
qqinpage a = new qqinpage();
a.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
客户端代码
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class qqinpage2 extends JFrame {
private JLabel ipLabel, userLabel, serverLabel, meanLabel;
private JButton inButton, outButton;
private JTextField ipField, userField, serverField;
private JRadioButton meanButton, mean2Button;
private JPanel ipPanel, userPanel, serverPanel, meanPanel, lastPanel;
public qqinpage2() {
ipLabel = new JLabel("请输入你要连入的IP地址:");
userLabel = new JLabel("请 输 入 你 的 用 户 名:");
serverLabel = new JLabel("请输入你 要接入的 端 口:");
meanLabel = new JLabel("请选择你需要的聊天方式:");
inButton = new JButton("连接");
outButton = new JButton("退出");
meanButton = new JRadioButton("双人");
mean2Button = new JRadioButton("多人");
ButtonGroup bg = new ButtonGroup();
bg.add(meanButton);
bg.add(mean2Button);
meanButton.setSelected(true);
ipField = new JTextField(20);
ipField.setText("127.0.0.1");
userField = new JTextField(20);
serverField = new JTextField(20);
ipPanel = new JPanel(new FlowLayout());
userPanel = new JPanel(new FlowLayout());
serverPanel = new JPanel(new FlowLayout());
meanPanel = new JPanel(new FlowLayout());
lastPanel = new JPanel(new FlowLayout());
ipPanel.add(ipLabel);
ipPanel.add(ipField);
userPanel.add(userLabel);
userPanel.add(userField);
serverPanel.add(serverLabel);
serverPanel.add(serverField);
meanPanel.add(meanLabel);
meanPanel.add(meanButton);
meanPanel.add(mean2Button);
lastPanel.add(inButton);
lastPanel.add(outButton);
addListener();
Container container = getContentPane();
container.setLayout(new GridLayout(5, 1));
container.add(ipPanel);
container.add(userPanel);
container.add(serverPanel);
container.add(meanPanel);
container.add(lastPanel);
setBounds(600, 200, 500, 250);
setTitle("客户端");
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void addListener() {
outButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
inButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (ipField.getText().equals("")) {
JOptionPane.showMessageDialog(null, "请输入ip", "提示", JOptionPane.INFORMATION_MESSAGE);
} else if (userField.getText().equals("")) {
JOptionPane.showMessageDialog(null, "请输入用户名", "提示", JOptionPane.INFORMATION_MESSAGE);
} else if (!meanButton.isSelected() && !mean2Button.isSelected()) {
JOptionPane.showMessageDialog(null, "请选择聊天方式", "提示", JOptionPane.INFORMATION_MESSAGE);
} else if (serverField.getText().equals("")) {
JOptionPane.showMessageDialog(null, "请输入接口", "提示", JOptionPane.INFORMATION_MESSAGE);
} else if (mean2Button.isSelected()) {
dispose();
new ClientFrame(userField.getText(), ipField.getText(), Integer.parseInt(serverField.getText()));
} else if (meanButton.isSelected()) {
dispose();
new ClientTPC(userField.getText(), ipField.getText(), Integer.parseInt(serverField.getText()));
}
}
});
}
public static void main(String[] args) {
qqinpage2 a = new qqinpage2();
a.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
1.3,后台代码
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ServerTPC extends JFrame {
private JTextField enterField;
private JTextArea displayArea;
private ObjectOutputStream output;
private ObjectInputStream input;
private ServerSocket server;
private Socket connection;
private JButton but;
private JPanel panel;
public ServerTPC(int i) {
super("管理员");
panel = new JPanel(new FlowLayout());
but = new JButton("发送");
Container container = getContentPane();
enterField = new JTextField(20);
enterField.setEditable(false);
enterField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sendData(e.getActionCommand());
enterField.setText("");
}
});
but.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sendData(e.getActionCommand());
enterField.setText("");
}
});
try {
server = new ServerSocket(i, 100);
} catch (IOException e1) {
JOptionPane.showMessageDialog(null, "端口被占用请 重新选择", "提示", JOptionPane.INFORMATION_MESSAGE);
}
panel.add(enterField);
panel.add(but);
container.add(panel, BorderLayout.SOUTH);
displayArea = new JTextArea();
displayArea.setEditable(false);
container.add(new JScrollPane(displayArea), BorderLayout.CENTER);
setBounds(600, 200, 500, 250);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
Thread a = new Thread(new Roll());
a.start();
}
private void waitForConnection() throws IOException {
displayMessage("等待用户接入");
connection = server.accept();
}
private void getStreams() throws IOException {
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
}
private void processConnection() throws IOException {
String message = "连接成功";
sendData(message);
setTextFieldEditable(true);
try {
do {
message = (String) input.readObject();
displayMessage("\n" + message);
} while (true);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "好友已下线", "提示", JOptionPane.INFORMATION_MESSAGE);
}
}
private void closeConnection() {
displayMessage("对话结束\n");
setTextFieldEditable(false);
try {
output.close();
input.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private void sendData(String message) {
try {
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy年MM月dd日HH:mm:ss");
output.writeObject("管理员:" + sf.format(date) + "\n" + message);
output.flush();
displayMessage("\n管理员:" + sf.format(date) + "\n" + message);
} catch (Exception e) {
displayArea.append("\n发生错误");
}
}
private void displayMessage(final String messageToDisplay) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
displayArea.append(messageToDisplay);
displayArea.setCaretPosition(displayArea.getText().length());
}
});
}
private void setTextFieldEditable(final boolean editable) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
enterField.setEditable(editable);
}
});
}
class Roll implements Runnable {
public void run() {
try {
while (true) {
try {
waitForConnection();
getStreams();
processConnection();
} catch (EOFException e) {
System.out.println("这里发生了错误请及时修复");
} finally {
closeConnection();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ClientTPC extends JFrame{
private JTextField enterField;
private JTextArea displayArea;
private ObjectOutputStream output;
private ObjectInputStream input;
private String message="";
private String chatServer,userName;
private Socket client;
private JButton but;
private JPanel panel;
private int server;
public ClientTPC(String username,String ip,int i) {
super("客户");
but=new JButton("发送");
panel=new JPanel(new FlowLayout());
chatServer=ip;
server=i;
userName=username;
Container c=getContentPane();
enterField=new JTextField(20);
enterField.setEditable(false);
enterField.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
sendData(e.getActionCommand());
enterField.setText( "" );
}
});
panel.add(enterField);
panel.add(but);
c.add(panel,BorderLayout.SOUTH);
displayArea=new JTextArea();
displayArea.setEditable(false);
c.add(new JScrollPane(displayArea),BorderLayout.CENTER);
setBounds(600, 200, 500, 250);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
Thread a=new Thread(new Roll());
a.start();
}
private void connectionToServer() throws IOException{
displayMessage("尝试连接");
client=new Socket(InetAddress.getByName(chatServer),server);
}
private void getStreams() throws IOException{
output=new ObjectOutputStream(client.getOutputStream());
output.flush();
input=new ObjectInputStream(client.getInputStream());
}
private void processConnection()throws IOException{
setTextFieldEditable(true);
try {
do {
message=(String)input.readObject();
displayMessage("\n"+message);
} while (true);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "服务器已关闭", "提示", JOptionPane.INFORMATION_MESSAGE);
}
}
private void closeConnection() {
displayMessage("\n断开连接");
setTextFieldEditable(false);
try {
output.close();
input.close();
client.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private void sendData(String message) {
try {
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy年MM月dd日HH:mm:ss");
output.writeObject(userName+":"+sf.format(date)+"\n"+message);
output.flush();
displayMessage("\n"+userName+":"+sf.format(date)+"\n"+message);
} catch (Exception e) {
displayArea.append("\n发生了错误");
}
}
private void displayMessage(final String messageToDisplay) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
displayArea.append(messageToDisplay);
displayArea.setCaretPosition(displayArea.getText().length());
}
});
}
private void setTextFieldEditable(final boolean editable) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
enterField.setEditable(editable);
}
});
}
class Roll implements Runnable{
public void run() {
try {
connectionToServer();
getStreams();
processConnection();
} catch (EOFException e1) {
System.out.println("客户断开连接");
} catch(IOException e2) {
e2.printStackTrace();
} finally {
closeConnection();
}
}
}
}
2,多人聊天模式
2.1,简介
思想:服务器作为一个独立线程,开启ServerSocket,通过while循环,不断的等待用户接入,每接入一个用户将它的socket放入HashSet,HashSet中的所有socket即是我们的用户。服务器开启子线程,传入新的socket对象,子线程run方法中获取输入流,通过while循环读取消息并发送给所有的socket。
流程图:
效果图:
2.2,后台逻辑代码
前端代码同1.2
服务端代码
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.JOptionPane;
public class Server {
private ServerSocket serverSocket;
private HashSet<Socket> allSockets;
public Server(int i) {
try {
serverSocket = new ServerSocket(i);
JOptionPane.showMessageDialog(null, "服务器已启动\n请运行客户端", "提示", JOptionPane.INFORMATION_MESSAGE);
} catch (Exception e) {
e.printStackTrace();
}
allSockets = new HashSet<Socket>();
try {
startService();
} catch (IOException e) {
System.out.println("错误");
}
}
public void startService() throws IOException {
while (true) {
Socket s = serverSocket.accept();
System.out.println("用户已进入聊天室");
allSockets.add(s);
new ServerThread(s).start();
}
}
private class ServerThread extends Thread {
Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
public void run() {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true) {
String str = br.readLine();
sendMessageTOAllClient(str);
}
} catch (Exception e) {
System.out.println("用户退出聊天室");
}
}
public void sendMessageTOAllClient(String message) throws IOException {
for (Socket s : allSockets) {
PrintWriter pw = new PrintWriter(s.getOutputStream());
pw.println(message);
pw.flush();
}
}
}
}
客户端代码
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.IOException;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javafx.scene.control.ScrollPane;
public class ClientFrame extends JFrame {
private JPanel contentPane,panel;
private JTextField tfMessage;
private JButton btnSend;
private JTextArea textArea;
private String userName;
private ChatRoomClient client;
public ClientFrame(String userName,String ip,int i) {
textArea=new JTextArea(10,10);
textArea.setEditable(false);
tfMessage =new JTextField(20);
btnSend = new JButton("发送");
try {
client = new ChatRoomClient(ip, i);
textArea.setText("连接成功\n");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e2) {
e2.printStackTrace();
}
setTitle("客户端");
tfMessage.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy年MM月dd日HH:mm:ss");
client.sendMessage(userName + ":" + sf.format(date) + ":\n" + tfMessage.getText());
tfMessage.setText("");
}
});
btnSend.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy年MM月dd日HH:mm:ss");
client.sendMessage(userName + ":" + sf.format(date) + ":\n" + tfMessage.getText());
tfMessage.setText("");
}
});
this.userName = userName;
ReadMessageThread messageThread = new ReadMessageThread();
messageThread.start();
Container c=getContentPane();
contentPane = new JPanel();
contentPane.setLayout(new BorderLayout());
panel = new JPanel();
panel.setLayout(new FlowLayout());
contentPane.add(new JScrollPane(textArea),BorderLayout.CENTER);
panel.add(tfMessage);
panel.add(btnSend);
contentPane.add(panel,BorderLayout.SOUTH);
c.add(contentPane);
setBounds(100, 100, 450, 300);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private class ReadMessageThread extends Thread {
public void run() {
while (true) {
String str = client.reciveMessage();
textArea.append(str + "\n");
}
}
}
}import java.io.*;
import java.net.*;
public class ChatRoomClient {
private Socket socket;
private BufferedReader bufferReader;
private PrintWriter pWriter;
public ChatRoomClient(String host, int port) throws UnknownHostException, IOException {
socket = new Socket(host, port);
bufferReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
pWriter = new PrintWriter(socket.getOutputStream());
}
public void sendMessage(String str) {
pWriter.println(str);
pWriter.flush();
}
public String reciveMessage() {
try {
return bufferReader.readLine();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void close() {
try {
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}