1. 说明
此项目使用到的Java基础知识:
- Java网络通信
- Java多线程
- Java输入输出流
- Java AWT 图形用户界面绘制
每个知识点参考教程:
- Java基础_18 | Java中网络通信程序的设计(url爬虫,TCP/UDP socket程序,socket文件传输程序)
- Java基础_17 | Java多线程程序设计(Java中两种创建线程的方法、多线程之间的同步和互斥)
- Java基础_16 | Java中的输入输出系统(字节流、字符流)
- Java基础_15 | Java中的图形用户界面包AWT使用详解
如果有兴趣,还可以添加网络文件传输功能,参考教程:
2. 服务端源码
//服务器端
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
public class Server {
public static void main(String[] args) {
ServeMainFrame serveMainFrame = new ServeMainFrame("服务器"); //创建主窗体,标题为“服务器”
serveMainFrame.setVisible(true); //设置主窗体可视化
}
}
/*主窗体类*/
class ServeMainFrame extends Frame{
private final int DEFAULT_WDITH = 500, //窗体默认宽度
DEFAULT_HEIGHT = 400; //窗体默认高度
private Font font = new Font("name",Font.PLAIN,18);
private TextField portInput = new TextField("8000",5), //端口号输入文本框(默认8000)
userInput = new TextField("",46); //用户输入文本框
private TextArea receieveInput = new TextArea("Welcome to Server!",12,42); //聊天记录显示文本域
private Panel setPanel = new Panel(), //设置界面(容器)(容器默认FlowLayout)
receievePanel = new Panel(), //接收界面(容器)
sendPanel = new Panel(); //发送界面(容器)
private StartButton startButton = new StartButton("Start");
private ServerSocket ss = null; //创建服务器套接字(必须要初始化null)
private Socket s = null; //用于接收处理客户端请求返回的套接字
DataInputStream dis = null;
private DataOutputStream dos = null;
private ServerSendButton serverSendButton = new ServerSendButton("send");
private ReceieveClient receieveClient =null;
public ServeMainFrame(String title) {
super(title); //调用父类构造方法,生成带标题的窗体
addWindowListener(new WindowsClosed()); //添加窗体监听器,用于关闭窗口
setBounds(80, 80, DEFAULT_WDITH, DEFAULT_HEIGHT); //设置窗体位置和大小
setResizable(false); //设置用户不可调整大小
add(setPanel,"North");//添加端口号设置容器到窗体
setPanel.add(new Label("Port"));
setPanel.add(portInput);
setPanel.add(startButton);
add(receievePanel, "Center"); //添加聊天记录显示容器到窗体
receieveInput.setFont(font);
receievePanel.add(receieveInput, "Center");
add(sendPanel, "South"); //添加用户发送容器到窗体
sendPanel.add(new Label("say: "));
sendPanel.add(userInput);
sendPanel.add(serverSendButton);
}
/*启动按钮(实现监听器接口)*/
class StartButton extends Button implements ActionListener{
public StartButton(String name) {
super(name);
addActionListener(this); //自身已经实现监听器接口,很重要的代码!!!
}
public void actionPerformed(ActionEvent e) {
try {
setEnabled(false);
ss = new ServerSocket(Integer.valueOf(portInput.getText())); //利用portInput中的端口号转化为整数,创建一个ServerSocket
receieveInput.append("\nserver starting......"); //显示server starting......
s = ss.accept(); //等待客户端的连接请求
receieveInput.append("\nclient contect successfully"); //连接成功后显示client contect successfully
//创建从客户端的输入流
dos = new DataOutputStream(s.getOutputStream());
dis =new DataInputStream(s.getInputStream());
receieveClient = new ReceieveClient(); //创建一个线程,读取客户端输入
receieveClient.start();; //启动该线程
}
catch(IOException ioe) {
receieveInput.append('\n'+ioe.toString());
}
finally {
}
}
}
/*创建一个线程,读取客户端输入*/ //如果实现Runable接口,则会进入死循环
class ReceieveClient extends Thread{
public void run() {
try {
String str = dis.readUTF();
while(str != null) {
receieveInput.append('\n'+"client say: "+ str);
str = dis.readUTF();
}
}
catch(IOException ioe) {
receieveInput.append('\n'+ioe.toString());
}
}
}
/*服务器发送按钮*/
class ServerSendButton extends Button implements ActionListener{
public ServerSendButton(String name) {
super(name);
addActionListener(this); //自身已经实现监听器接口,很重要的代码!!!
}
public void actionPerformed(ActionEvent e) {
try {
dos.writeUTF(userInput.getText());
dos.flush();
receieveInput.append('\n'+"say to client: "+userInput.getText());
userInput.setText("");
}
catch(IOException ioe) {
receieveInput.append('\n'+ioe.toString());
}
}
}
/*继承自Windows监听器,重写关闭窗体的方法*/
class WindowsClosed extends WindowAdapter{
public void windowClosing(WindowEvent e) {
System.exit(-1); //程序终止
}
}
}
运行起来效果如下:
3.客户端源码
//客户端
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
public class Client {
public static void main(String[] args) {
ClientMainFrame clientMainFrame = new ClientMainFrame("客户端"); //创建主窗体,标题为“服务器”
clientMainFrame.setVisible(true); //设置主窗体可视化
}
}
/*主窗体类*/
class ClientMainFrame extends Frame {
private final int DEFAULT_WDITH = 500, //窗体默认宽度
DEFAULT_HEIGHT = 400; //窗体默认高度
private Font font = new Font("name",Font.PLAIN,18);
private TextField ipInput = new TextField("127.0.0.1",8), //ip地址输入文本框(默认127.0.0.1)
portInput = new TextField("8000",5), //端口号输入文本框(默认8000)
userInput = new TextField("",46); //用户输入文本框
private TextArea receieveInput = new TextArea("Welcome to Client!",12,42); //聊天记录显示文本域
private Panel setPanel = new Panel(), //设置界面(容器)(容器默认FlowLayout)
receievePanel = new Panel(), //接收界面(容器)
sendPanel = new Panel(); //发送界面(容器)
private ConnectButton connectButton = new ConnectButton("Connect");
private ClientSendButton clienttSendButton = new ClientSendButton("send");
private Socket s = null; //用于接收处理客户端请求返回的套接字
private DataOutputStream dos = null; //客户端输出流
private DataInputStream dis = null;
ReceieveServer receieveServer = null;
public ClientMainFrame(String title) {
super(title); //调用父类构造方法,生成带标题的窗体
addWindowListener(new WindowsClosed()); //添加窗体监听器,用于关闭窗口
setBounds(600, 80, DEFAULT_WDITH, DEFAULT_HEIGHT); //设置窗体位置和大小
setResizable(false); //设置用户不可调整大小
add(setPanel,"North"); //添加设置容器到窗体
setPanel.add(new Label("Server IP: "));
setPanel.add(ipInput);
setPanel.add(new Label("Port: "));
setPanel.add(portInput);
setPanel.add(connectButton);
add(receievePanel, "Center"); //添加聊天记录显示容器到窗体
receieveInput.setFont(font);
receievePanel.add(receieveInput, "Center");
add(sendPanel, "South"); //添加用户发送容器到窗体
sendPanel.add(new Label("say: "));
sendPanel.add(userInput);
sendPanel.add(clienttSendButton);
}
/*连接按钮(实现监听器接口)*/
class ConnectButton extends Button implements ActionListener{
public ConnectButton(String name) {
super(name);
addActionListener(this); //自身已经实现监听器接口,很重要的代码!!!
}
public void actionPerformed(ActionEvent e) {
try {
setEnabled(false);
s = new Socket(ipInput.getText(),Integer.valueOf(portInput.getText())); //等待客户端的连接请求
receieveInput.append("\nserver contect successfully!"); //连接成功后显示client contect successfully
dos = new DataOutputStream(s.getOutputStream());
dis = new DataInputStream(s.getInputStream());
receieveServer = new ReceieveServer();
receieveServer.start();
}
catch(IOException ioe) {
receieveInput.append('\n'+ioe.toString());
}
finally {
}
}
}
/*客户端发送按钮*/
class ClientSendButton extends Button implements ActionListener{
public ClientSendButton(String name) {
super(name);
addActionListener(this); //自身已经实现监听器接口,很重要的代码!!!
}
public void actionPerformed(ActionEvent e) {
try {
dos.writeUTF(userInput.getText());
dos.flush();
receieveInput.append('\n'+"say to serve: "+userInput.getText());
userInput.setText("");
}
catch(IOException ioe) {
receieveInput.append('\n'+ioe.toString());
}
}
}
/*创建一个线程,读取服务器输入*/
class ReceieveServer extends Thread{
public void run() {
try {
String str = dis.readUTF();
while(str != null){
receieveInput.append('\n'+"serve say: "+str);
str = dis.readUTF();
}
}
catch(IOException ioe) {
receieveInput.append('\n'+ioe.toString());
}
}
}
/*继承自Windows监听器,重写关闭窗体的方法*/
class WindowsClosed extends WindowAdapter{
public void windowClosing(WindowEvent e) {
System.exit(-1); //程序终止
}
}
}
运行起来效果如下:
4. 运行效果
启动服务器监听
客户端连接服务器
客户端连接之后在服务端也可以看到:
客户端发送消息
服务端发送消息
接收更多精彩文章及资源推送,欢迎订阅我的微信公众号:『mculover666』。