2021-10-31

实现一对具有聊天功能的客户端与服务端 如图:
2021-10-31

一、总步骤

1.建立网络连接
2.通过管道传输信息
3.增加一个图形化界面
4.在图形化界面上添加动作监听器
5.在客户端/服务端添加收发信息功能

注意事项:先启用服务端,然后开启客户端

二、详细过程

2.1建立网络连接

服务端通过Socket连接客户端,分为三步
1.服务端监听
2.客户端请求
3.确认连接
1.创建一个端口号为8888,IP地址为本机地址的socket

ServerSocket serverSocket = new ServerSocket(8888);

2.进入监听状态

Socket client = serverSocket.accept();

3.确认连接(创建一个新的客户端类,在新类中写)

Socket socket = new Socket("127.0.0.1", 8888);

2.2.通过管道传输信息

管道的特点是,通过输入流接受其他类处理的结果,加工后通过输出流传出
1.在服务端创建输入输出流

InputStream inputStream = client.getInputStream();
OutputStream outputStream = client.getOutputStream();

2.在客户端创建输出输出流

2.3.增加一个图形化界面

建立图形化界面分为

1.建立窗体,添加文本框

2.添加发送消息按钮

1.建立窗体,添加文本框 先获取输入输出流,并设置窗体类的构造方法

创建MsgUI类

为了实现文本传输,需要传递outputStream对象,将文本框jTextPane1中的文字传入outputStream对象中,返回jTextPane用于显示文字

    OutputStream outputStream;
    MsgUI(OutputStream outputStream) {
        this.outputStream = outputStream;

    }
    

当MsgUI被调用时,执行initUI方法,建立一个图形化界面

public JTextPane initUI(String title) {
        setTitle(title);
        setSize(800, 600);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setLocationRelativeTo(null); // 在*
        setLayout(new FlowLayout());
        //添加一个两个文本框,一个用于读入输入的信息,另一个用于接受消息
        JTextPane jTextPane = new JTextPane();
        jTextPane.setPreferredSize(new Dimension(200, 200));
        JScrollPane jScrollPane = new JScrollPane(jTextPane);

        JTextPane jTextPane1 = new JTextPane();
        jTextPane1.setPreferredSize(new Dimension(200, 200));
        JScrollPane jScrollPane1 = new JScrollPane(jTextPane1);
        add(jScrollPane);
        add(jScrollPane1);
        setVisible(true);
   return jTextPane;
    }

2.添加消息发送按钮

 JButton jButton = new JButton("send");
 add(jButton);

2.4.在图形化界面上添加动作监听器

为按钮绑定动作监听器,实现读入文本,点击按钮发送的功能

在initUI方法中为按钮绑定监听器,当监听器调用时用文本框中的文字修改outputStream中的文本

        MsgListener msgListener = new MsgListener(jTextPane1, this.outputStream);
        jButton.addActionListener(msgListener);

创建MsgListener类,含有outoutStream和jTextPane两个参数

    public class MsgListener implements ActionListener{
    JTextPane jTextPane;
    OutputStream outputStream;

    MsgListener(JTextPane jTextPane, OutputStream outputStream) {
        this.outputStream = outputStream;
        this.jTextPane = jTextPane;
    }

实现抽象方法,当按钮按下时传输文本

    public void actionPerformed(ActionEvent e) {

        try {
            String message = jTextPane.getText();
            byte[] messages = message.getBytes();
            outputStream.write(messages.length);
            outputStream.write(jTextPane.getText().getBytes());
            outputStream.flush();

        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

2.5 在客户端/服务端中调用添加消息收发功能

以客户端为例: 1.实例化窗体

        MsgUI msgUI = new MsgUI(outputStream);
        JTextPane messagePane = msgUI.initUI("client");

2.读入从inputStream获得的信息,转为文字显示在窗体上

while (true) {

            //传入地址,构造字节数组
            int msgLength = inputStream.read();
            byte[] msgBytes = new byte[120];
            //读入文本
            inputStream.read(msgBytes);
            
            //构造字符串,接受字符数组的信息
            String getMessage = new String(msgBytes);
            //缓存文本框中的文字,从而连续收发消息
            String msg = messagePane.getText();

            messagePane.setText(msg + "server say: " + getMessage + "\n");

三、源代码

客户端

package Server2;

import javax.swing.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class MsgClient {
    public static void main(String[] args) throws IOException {
        Socket serverSocket = new Socket("127.0.0.1", 8888);

        // 输入输出流对象
        InputStream inputStream = serverSocket.getInputStream();
        OutputStream outputStream = serverSocket.getOutputStream();
        MsgUI msgUI = new MsgUI(outputStream);
        JTextPane messagePane = msgUI.initUI("client");

        while (true) {

            //传入地址,构造字节数组
            int msgLength = inputStream.read();
            byte[] msgBytes = new byte[120];
            //读入
            inputStream.read(msgBytes);

            String getMessage = new String(msgBytes);
//            System.out.println("来自服务器的消息:" + "长度为:" + msgLength + " " + getMessage);

            String msg = messagePane.getText();

            messagePane.setText(msg + "server say: " + getMessage + "\n");


          


    }


    



监听器

package Server2;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import java.io.OutputStream;

public class MsgListener implements ActionListener {
    JTextPane jTextPane;
    OutputStream outputStream;

    MsgListener(JTextPane jTextPane, OutputStream outputStream) {
        this.outputStream = outputStream;
        this.jTextPane = jTextPane;
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        try {
            String message = jTextPane.getText();
            byte[] messages = message.getBytes();
            outputStream.write(messages.length);
            outputStream.write(jTextPane.getText().getBytes());
            outputStream.flush();

        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

   

    
    
}


服务端

package Server2;

import javax.swing.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class MsgServer {
    public static void main(String args[]) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8888);  //推荐使用5000+端口,防冲突

        Socket client = serverSocket.accept(); //监听连接

        InputStream inputStream = client.getInputStream();
        OutputStream outputStream = client.getOutputStream();

        MsgUI msgUI = new MsgUI(outputStream);
        JTextPane messagePane = msgUI.initUI("server");
        while (true) {
            int msgLength = inputStream.read();
            System.out.println("message length is " + msgLength);
            byte[] msgBytes = new byte[msgLength];
            inputStream.read(msgBytes);

            String getMsg = new String(msgBytes);
            System.out.println("client say: " + getMsg);
            String msg = messagePane.getText();
            messagePane.setText(msg + "client say: " + getMsg + "\n");
        }
    }
}

图形界面

package Server2;

import javax.swing.*;
import java.awt.*;
import java.io.OutputStream;

public class MsgUI extends JFrame {
    OutputStream outputStream;
    Graphics graphics;

    MsgUI(OutputStream outputStream) {
        this.outputStream = outputStream;

    }


    public JTextPane initUI(String title) {
        setTitle(title);
        setSize(800, 600);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setLocationRelativeTo(null); // 在*
        setLayout(new FlowLayout());
        JTextPane jTextPane = new JTextPane();
        jTextPane.setPreferredSize(new Dimension(200, 200));
        JScrollPane jScrollPane = new JScrollPane(jTextPane);

        JTextPane jTextPane1 = new JTextPane();
        jTextPane1.setPreferredSize(new Dimension(200, 200));
        JScrollPane jScrollPane1 = new JScrollPane(jTextPane1);

        JButton jButton = new JButton("send");
        add(jScrollPane);
        add(jScrollPane1);
        add(jButton);
        setVisible(true);

        graphics = getGraphics();
        MsgListener msgListener = new MsgListener(jTextPane1, this.outputStream);
        jButton.addActionListener(msgListener);

        return jTextPane;
    }


}

上一篇:css clip-path和drop-shadow生成自定义图形、阴影


下一篇:PyQt5-02-PyQt5的QApplication类