注意
完整实验报告及源码链接:https://download.csdn.net/download/qq_29711355/85641623
一、实验目的:
练习Socket网络访问方法,理解网络程序的设计思想与实现方法。
二、实验内容:
设计网络聊天程序,实现如下功能:
(1)聊天两端具有相同的界面,包括能输入消息的文本框、发送消息按钮、消息列表文本框;
(2)任意一端均可以实时发送和接收消息,并在自身的消息列表中显示消息记录。
三、实验要求:
1、正确设计图形用户界面;
2、完成网络访问的界面和功能设计;
3、进行测试并分析测试结果;
4、简要说明你在该实验中的收获与体会。
参考代码
Client 类
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Client {//客户端
private Socket socket;
private InputStream in;
private OutputStream out;
private PrintWriter writer;
private BufferedReader reader;
private MessageAble msgAble;
public Client(String host,int port,MessageAble msgAble) {
this.msgAble = msgAble;
try {
socket = new Socket(host,port);//发出请求,主机地址、端口
in = socket.getInputStream();
out = socket.getOutputStream();
writer = new PrintWriter(out);//把out包装一下
reader = new BufferedReader(
new InputStreamReader(in));
startReceiveMsg();//开始接受消息
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void sendMessage(String msg) {
writer.println(msg);
writer.flush();//传消息
}
private void startReceiveMsg(){//开始监听接收消息 一接受到就打印出来
new Thread(//一个匿名内部类来启动线程,监听reader有没得内容,一旦有,就打印出来
new Runnable() {
public void run() {
// TODO Auto-generated method stub
try {
String line;
while((line = reader.readLine())!=null) {//一个死循环 一直监听
//System.out.println(line);
msgAble.dealMessage(line);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
public void close() {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
ClientUI 类
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class ClientUI {
private JTextArea chatArea;
private JTextField messageField;
private Client client;
private JTextField adressField;
public ClientUI() {
JFrame frame = new JFrame("客户端");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800,1000);
frame.setLayout(new BorderLayout());
chatArea = new JTextArea();//聊天框
chatArea.setFont(new Font("微软雅黑",Font.BOLD,30));
JScrollPane scrollPane = new JScrollPane(chatArea);
frame.add(scrollPane,BorderLayout.CENTER);
JPanel panel = new JPanel();
messageField = new JTextField();
messageField.setColumns(20);
messageField.setFont(new Font("微软雅黑",Font.BOLD,30));
JButton sentBtn = new JButton("发送");
sentBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
String msg = messageField.getText();
chatArea.append("服务端:"+msg+"\n");
client.sendMessage(msg);
}
});
panel.add(messageField);
panel.add(sentBtn);
frame.add(panel,BorderLayout.SOUTH);
JPanel northPan = new JPanel();
northPan.add(new JLabel("连接:"));
adressField = new JTextField();
adressField.setColumns(20);
JButton startBtn = new JButton("连接");
startBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
startConnect();
}
});
northPan.add(adressField);
northPan.add(startBtn);
frame.add(northPan,BorderLayout.NORTH);
frame.setVisible(true);
}
private void startConnect() {
String address = adressField.getText();
String[] strs=address.split(":");
String host = strs[0];
int port = Integer.parseInt(strs[1]);
client = new Client(host,port,new MessageAble() {//构造server的时候就告诉服务器接收到的消息由ui这边来处理
public void dealMessage(String msg) {
//处理接收到的消息
chatArea.append("客户端:"+msg+"\n");
}
});
}
public static void main(String[] args) {
new ClientUI();
}
}
MessageAble 类
public interface MessageAble {
public void dealMessage(String msg);
}
Server 类
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
private ServerSocket serverSocket;
private InputStream in;
private OutputStream out;
private PrintWriter writer;
private BufferedReader reader;
private MessageAble messageAble;
//在构造函数中开始监听,当有用户连上后,就产生输入输出流对象,并且开始接收消息
public Server(int port, MessageAble messageAble) {//服务器程序
this.messageAble = messageAble;//谁调用谁处理
try {
serverSocket = new ServerSocket(port);
//只有一个客户端一个服务器所以我们直接accept 不用担心被阻塞
Socket socket = serverSocket.accept();//等待客户端发出链接请求
in = socket.getInputStream();//把输入输出流流进行保存
out = socket.getOutputStream();
writer = new PrintWriter(out);//把out包装一下,可以发送字符串
reader = new BufferedReader(
new InputStreamReader(in));//字节流包装成字符流
startReceiveMsg();//开始接受消息
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendMessage(String msg) {//发消息
writer.println(msg);
writer.flush();//传消息
}
private void startReceiveMsg(){//开始监听接收消息 一接受到就打印出来
new Thread(//一个匿名内部类来启动线程,监听reader有没得内容,一旦有,就打印出来
new Runnable() {//非Thread类子类的类提供的一种激活方式,Runnable只有一个run方法
public void run() {
String line;
try {
while((line = reader.readLine())!=null) {//一个死循环 一直监听,监听reader
//System.out.println(line);
messageAble.dealMessage(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
).start();
}
public void close() {//关闭
try {
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
ServerUI 类
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class ServerUI {
private JTextArea chatArea;
private JTextField messageField;
private Server server;
private JTextField portField;
public ServerUI() {
JFrame frame = new JFrame("服务器");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800,1000);
frame.setLayout(new BorderLayout());
chatArea = new JTextArea();//聊天框
chatArea.setFont(new Font("微软雅黑",Font.BOLD,30));
// JScrollPane scrollPane = new JScrollPane(chatArea);
frame.add(chatArea,BorderLayout.CENTER);
JPanel panel = new JPanel();
messageField = new JTextField();
messageField.setColumns(20);
messageField.setFont(new Font("微软雅黑",Font.BOLD,30));
JButton sentBtn = new JButton("发送");
sentBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
String msg = messageField.getText();
chatArea.append("服务端:"+msg+"\n");
server.sendMessage(msg);
}
});
panel.add(messageField);
panel.add(sentBtn);
frame.add(panel,BorderLayout.SOUTH);
JPanel northPan = new JPanel();
northPan.add(new JLabel("监听端口:"));
portField = new JTextField();//输入框
portField.setColumns(20);
JButton startBtn = new JButton("监听");
startBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
startServer();
}
});
northPan.add(portField);
northPan.add(startBtn);
frame.add(northPan,BorderLayout.NORTH);
frame.setVisible(true);
}
private void startServer() {
int port = Integer.parseInt(portField.getText());
server = new Server(port,new MessageAble() {//构造server的时候就告诉服务器接收到的消息由ui这边来处理
public void dealMessage(String msg) {
//处理接收到的消息
chatArea.append("客户端:"+msg+"\n");
}
});
}
public static void main(String[] args) {
new ServerUI();
}
}