直接上代码。
package Experiment3;
//尝试一下通过Java提供的UI,改变界面
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
//在客户端的textarea添加scrollpane
//更改ui风格适应windows11
//客户端退出时在服务器端添加相应。
public class ClientChat {
//这是一个main方法,是程序的入口:
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
ClientJframe clientJframe = new ClientJframe();
clientJframe.init();
}
}
class ClientJframe extends JFrame {
//GUI布局
//聊天记录显示区
JLabel HeadLabel = new JLabel("聊天记录");
private JButton say = new JButton("Send");
private JButton exit = new JButton("Exit");
private Box vbox = Box.createVerticalBox();
private Box hbox = Box.createHorizontalBox();
private Box hBox2 = Box.createHorizontalBox();
private JTextArea ta = new JTextArea(200, 200);
JScrollPane clientScrollPane = new JScrollPane(
ta,
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER
);
//聊天记录输入区
private JTextField tf = new JTextField();
//端口
// 静态常量主机端口号
private static final String CONNSTR = "127.0.0.1";
// 静态常量服务器端口号
private static final int CONNPORT = 8888;
private Socket socket = null;
//Client发送数据
private DataOutputStream dataOutputStream = null;
//客户端连接上服务器判断符号
private boolean isConn = false;
/**
* 无参的构造方法 throws HeadlessException
*/
public ClientJframe() throws HeadlessException {
super();
}
public void init() throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
this.setTitle("客户端窗口");
hBox2.add(ta);
hBox2.add(clientScrollPane);
vbox.add(HeadLabel);
vbox.add(hBox2);
hbox.add(tf);
hbox.add(say);
hbox.add(exit);
vbox.add(hbox);
this.add(vbox);
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
this.setSize(400,400);
// 添加监听,使回车键可以输入数据(判断数据合法性),
// 并輸入到聊天框,换行
tf.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String strSend = tf.getText();
if (strSend.trim().length() == 0) {
return;
}
//客户端信息strSend发送到服务器上
send(strSend);
tf.setText("");
}
});
say.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
String strSend = tf.getText();
if (strSend.trim().length() == 0) {
return;
}
//客户端信息strSend发送到服务器上
send(strSend);
tf.setText("");
}
});
exit.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
//关闭事件
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ta.setEditable(false);
tf.requestFocus();//光标聚焦在输入框上;
try {
socket = new Socket(CONNSTR, CONNPORT);
isConn = true;
} catch (Exception e) {
e.printStackTrace();
}
// 启动多线程
new Thread(new Receive()).start();
this.setVisible(true);
}
/**
* 客户端发送信息到服务器上的方法
*/
public void send(String str) {
try {
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataOutputStream.writeUTF(str);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
*
* @deprecated 多线程的类,实现了Runnable接口的类
*/
class Receive implements Runnable {
@Override
public void run() {
try {
while (isConn) {
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
String str = dataInputStream.readUTF();
//通讯消息
ta.append(str);
}
} catch (SocketException e) {
System.out.println("Server stoped!!");
ta.append("Server stoped!!");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
package Experiment3;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Iterator;
public class ServerChat {
//这是一个main方法,是程序的入口:
public static void main(String[] args) throws Exception {
ServerJframe serverJframe = new ServerJframe();
serverJframe.init();
}
}
class ServerJframe extends JFrame {
//GUI相关属性
JTextArea serverTa = new JTextArea(200,200);
JTextField serverTf = new JTextField();
private JLabel serverHeadLabel = new JLabel("聊天记录");
JButton startBtn = new JButton("启动");
JButton stopBtn = new JButton("停止");
JButton sendBtn = new JButton("发送");
private Box vbox = Box.createVerticalBox();
private Box hbox = Box.createHorizontalBox();
private Box hBox2 = Box.createHorizontalBox();
private JScrollPane scrollPane = new JScrollPane(serverTa);
//端口
private static final int PORT = 8888;
//ServerSocket
private ServerSocket serverSocket = null;
private Socket socket = null;
//Server接受数据
private DataInputStream dataInputStream = null;
// 多个客户端访问时,客户端对象存放入List中
private ArrayList ccList = new ArrayList();
// 服务器启动的标志 (其实ServerSocket ss 初始化出来时以为者服务器的启动)
private boolean isStart = false;
public void init() throws Exception {
this.setTitle("服务器端窗口");
this.setSize(400,400);
hbox.add(serverTf);
hbox.add(scrollPane);
vbox.add(serverHeadLabel);
vbox.add(hbox);
hBox2.add(serverTf);
hBox2.add(sendBtn);
hBox2.add(stopBtn);
hBox2.add(startBtn);
vbox.add(hBox2);
this.add(vbox);
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
this.setSize(400,400);
//判断服务器是否已经开启
//按钮监听监听服务器开启,置开始位false
startBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
if (serverSocket == null) {
serverSocket = new ServerSocket(PORT);
}
isStart = true;
//startServer();
serverTa.append("Server is in ready. \n");
} catch (Exception e1) {
e1.printStackTrace();
}
}
});
// 终止按钮监听停止服务器,置开始位true
stopBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
if (serverSocket != null) {
serverSocket.close();
isStart = false;
}
System.exit(0);
serverTa.append("Server has been quit Connection\n");
System.out.println("Server has been quit Connection\n");
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
sendBtn.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
String msg = serverTf.getText();
if(msg.equals("")){
JOptionPane.showMessageDialog(null,"请输入信息!","Warnning",JOptionPane.WARNING_MESSAGE);
}else{
serverTa.append("Server: "+msg+"\n");
serverTf.setText("");
Iterator iterator = ccList.iterator();
while(iterator.hasNext()){
ClientCoon cc = iterator.next();
cc.send(msg);
}
}
}
});
// this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// serverTa.setEditable(false);
this.setVisible(true);
startServer();
if (isStart) {
System.out.println("Started.\n");
} else {
JOptionPane.showMessageDialog(null,"Hasn't been started.","Error",JOptionPane.ERROR_MESSAGE);
}
}
public void startServer() throws Exception {
try {
try {
serverSocket = new ServerSocket(PORT);
isStart = true;
}catch (Exception e) {
e.printStackTrace();
}
while (isStart) {
socket = serverSocket.accept();
ccList.add(new ClientCoon(socket));
serverTa.append("\n" + "@" + socket.getInetAddress() + "/" + socket.getPort()+"Have been connected to the server");
}
} catch (SocketException e) {
System.out.println("Stream has been closed");
} catch (Exception e) {
e.printStackTrace();
}
}
class ClientCoon implements Runnable {
Socket socket = null;
public ClientCoon(Socket socket) {
this.socket = socket;
(new Thread(this)).start();
}
//接受客户端信息(多线程run()方法)
@Override
public void run() {
try {
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
// 为了让服务器能够接受到每个客户端的多句话
while (isStart) {
String str = dataInputStream.readUTF();
serverTa.append("\n@" + socket.getInetAddress() + "||" + socket.getPort() + ":" + str + "\n");
//服务器向每个客户端发送别的客户端发来的信息
// 遍历ccList,调用send方法,在客户端里接受应该是多线程的接受
String strSend = "\n" + socket.getInetAddress() + "||" + socket.getPort() + ":" + str + "\n";
Iterator iterator = ccList.iterator();
while (iterator.hasNext()) {
ClientCoon clientCoon = iterator.next();
clientCoon.send(strSend);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 服务器向每個连接对象发送数据的方法
public void send(String str) {
try {
DataOutputStream dataOutputStream = new DataOutputStream(this.socket.getOutputStream());
dataOutputStream.writeUTF(str);
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
运行结果如上图。