java程序实现聊天互动(二)

 解决 java程序实现聊天互动(一) 硬编码问题

将服务端和客户端的端口号和ip放置在配置文件中,同时在ServerChat.java和ClientChat.java使用static代码块

 

 

编写两个java文件:

ServerChat.java文件

ClientChat.java文件

windows + R 开启cmd黑窗口

 

在cmd黑窗口中运行:注意开启两个cmd窗口,称第一个为serverCMD,第二个为clientCMD

serverCMD:

    跳转到ServerChat.java文件所在的文件夹

        cd D:\otest

    编译ServerChat.java文件,编译后会新增一个ServerChat.class文件

        javac ServerChat.java

    运行ServerChat.class文件,注意运行时不要有 .class

        java ServerChat

 

clientCMD:

    跳转到ClientChat.java文件所在的文件夹

        cd D:\otest

    编译ClientChat.java文件,编译后会新增一个ClientChat.class文件

        javac ClientChat.java

    运行ClientChat.class文件,注意运行时不要有 .class

        java ClientChat

 

chat.properties文件

 

serverPort=8888

clientIp=127.0.0.1
clientPort=8888

  

 

ServerChat.java文件
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;

//说明:如果一个类,需要有界面显示,那么该类就需要继承自JFrame,此时,该类就可以被称为一个"窗体类"
//1.定义JFrame 窗体中的组件
//2.在构造方法中初始化窗体的组件
//3.使用网络编程完成数据的传输(TCP,UDP 协议)
//4.实现"发送"按钮的监听点击事件
//需要注意:文本域拼接数据时,实现自己换行,不要在发送数据中使用System.lineSeparator()换行
//这样会导致bw.newLine()与System.lineSeparator()两个换行导致使用BufferedReader读取时,无法正确的辨别需要的换行
//5.实现"回车键"发送数据
public class ServerChat extends JFrame implements ActionListener, KeyListener {
    public static void main(String[] args) {
        //调用构造方法
        new ServerChat();
    }

    //属性
    //文本域
    private JTextArea jta;
    //滚动条
    private JScrollPane jsp;
    //面板
    private JPanel jp;
    //文本框
    private JTextField jtf;
    //按钮
    private JButton jb;

    //输出流
    private BufferedWriter bw = null;

    //服务端的端口号
    private static int serverPort;
    //使用static 静态代码块读取外部配置文件
    static {
        Properties p = new Properties();
        try {
            //加载
            p.load(new FileReader("chat.properties"));
            //赋值属性值
            serverPort = Integer.parseInt(p.getProperty("serverPort"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //构造方法
    public ServerChat() {
        //初始化组件
        //文本域
        jta = new JTextArea();
        //注意:需要将文本域添加到滚动条中,实现滚动效果
        //滚动条
        jsp = new JScrollPane(jta);

        //面板
        jp = new JPanel();
        //文本框
        jtf = new JTextField(10);//文本框大小
        //按钮
        jb = new JButton("发送");//按钮名称
        //注意:需要将文本框与按钮添加到面板中
        jp.add(jtf);
        jp.add(jb);

        //注意:需要将滚动条和面板添加到窗体中
        this.add(jsp, BorderLayout.CENTER);
        this.add(jp,BorderLayout.SOUTH);//上北下南

        //注意:需要设置 标题、大小、位置、关闭、是否可见
        this.setTitle("聊天框 服务");//标题
        this.setSize(300,300);// 宽 高
        this.setLocation(300,300);// 水平 垂直
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//窗体关闭 程序退出
        this.setVisible(true);//是否可见

        /******************* TCP 服务端 start ****************************/
        //给"发送"按钮绑定一个监听点击事件
        jb.addActionListener(this);//让当前对象监听
        //给文本框绑定一个键盘点击事件
        jtf.addKeyListener(this);

        try {
            //1.创建服务端套接字
            ServerSocket serverSocket = new ServerSocket(serverPort);
            //2.等待客户端连接
            Socket socket = serverSocket.accept();
            //3.获取socket 通道的输入流(输入流是实现读取数据,一行一行读取)
            InputStream in = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            //4.获取socket 通道的输出流(输出流实现写出数据,也是写一行,换一行,刷新)
            OutputStream out = socket.getOutputStream();
            bw = new BufferedWriter(new OutputStreamWriter(out));

            //循环读取数据,并拼接到文本域中
            String line = null;
            while((line = br.readLine()) != null) {
                //将读取的数据拼接到文本域中显示
                jta.append(line + System.lineSeparator());//换行
            }
            //5.关闭serverSocket 通道
            serverSocket.close();
        } catch(IOException e) {
            e.printStackTrace();
        }

        /******************* TCP 服务端 end ****************************/

    }

    @Override
    public void actionPerformed(ActionEvent event) {
        //发送数据到socket通道中
        sendDataToSocket();
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode() == KeyEvent.VK_ENTER) {
            //发送数据到socket通道中
            sendDataToSocket();
        }
    }
    @Override
    public void keyTyped(KeyEvent e) {
    }
    @Override
    public void keyReleased(KeyEvent e) {
    }

    //将数据发送到socket通道中
    private void sendDataToSocket(){
        //1.获取文本框中发送的内容
        String text = jtf.getText();
        //2.拼接需要发送的数据内容
        text = "服务:" + text;
        //3.在自己文本域中显示
        jta.append(text + System.lineSeparator());

        try {
            //4.发送
            bw.write(text);
            bw.newLine();
            bw.flush();
            //5.清空文本框内容
            jtf.setText("");

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

  

ClientChat.java文件
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.*;
import java.net.Socket;
import java.util.Properties;

//说明:如果一个类,需要有界面显示,那么该类就需要继承自JFrame,此时,该类就可以被称为一个"窗体类"
//1.定义JFrame 窗体中的组件
//2.在构造方法中初始化窗体的组件
//3.使用网络编程完成数据的传输(TCP,UDP 协议)
//4.实现"发送"按钮的监听点击事件
//5.实现"回车键"发送数据
public class ClientChat extends JFrame implements ActionListener, KeyListener {
    public static void main(String[] args) {
        //调用构造方法
        new ClientChat();
    }

    //属性
    //文本域
    private JTextArea jta;
    //滚动条
    private JScrollPane jsp;
    //面板
    private JPanel jp;
    //文本框
    private JTextField jtf;
    //按钮
    private JButton jb;

    //输出流
    private BufferedWriter bw = null;

    //客户端IP
    private static String clientIp;
    //客户端端口号
    private static int clientPort;

    //使用static 静态代码块读取外部配置文件
    static {
        Properties p = new Properties();
        try {
            //加载
            p.load(new FileReader("chat.properties"));
            //赋值属性值
            clientPort = Integer.parseInt(p.getProperty("clientPort"));
            clientIp = p.getProperty("clientIp");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //构造方法
    public ClientChat() {
        //初始化组件
        //文本域
        jta = new JTextArea();
        //注意:需要将文本域添加到滚动条中,实现滚动效果
        //滚动条
        jsp = new JScrollPane(jta);

        //面板
        jp = new JPanel();
        //文本框
        jtf = new JTextField(10);//文本框大小
        //按钮
        jb = new JButton("发送");//按钮名称
        //注意:需要将文本框与按钮添加到面板中
        jp.add(jtf);
        jp.add(jb);

        //注意:需要将滚动条和面板添加到窗体中
        this.add(jsp, BorderLayout.CENTER);
        this.add(jp,BorderLayout.SOUTH);//上北下南

        //注意:需要设置 标题、大小、位置、关闭、是否可见
        this.setTitle("聊天框 服务");//标题
        this.setSize(300,300);// 宽 高
        this.setLocation(700,300);// 水平 垂直
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//窗体关闭 程序退出
        this.setVisible(true);//是否可见

        /******************* TCP 服务端 start ****************************/
        //给"发送"按钮绑定一个监听点击事件
        jb.addActionListener(this);//让当前对象监听
        //给文本框绑定一个键盘点击事件
        jtf.addKeyListener(this);

        try {
            //1.创建服务端套接字
            Socket socket = new Socket(clientIp,clientPort);
            //2.获取socket 通道的输入流(输入流是实现读取数据,一行一行读取)
            InputStream in = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            //3.获取socket 通道的输出流(输出流实现写出数据,也是写一行,换一行,刷新)
            OutputStream out = socket.getOutputStream();
            bw = new BufferedWriter(new OutputStreamWriter(out));

            //循环读取数据,并拼接到文本域中
            String line = null;
            while((line = br.readLine()) != null) {
                //将读取的数据拼接到文本域中显示
                jta.append(line + System.lineSeparator());//换行
            }
            //4.关闭serverSocket 通道
            socket.close();
        } catch(IOException e) {
            e.printStackTrace();
        }

        /******************* TCP 服务端 end ****************************/

    }

    @Override
    public void actionPerformed(ActionEvent event) {
        //发送数据到socket通道中
        sendDataToSocket();
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode() == KeyEvent.VK_ENTER) {
            //发送数据到socket通道中
            sendDataToSocket();
        }
    }
    @Override
    public void keyTyped(KeyEvent e) {
    }
    @Override
    public void keyReleased(KeyEvent e) {
    }

    //将数据发送到socket通道中
    private void sendDataToSocket(){
        //1.获取文本框中发送的内容
        String text = jtf.getText();
        //2.拼接需要发送的数据内容
        text = "客户:" + text;
        //3.在自己文本域中显示
        jta.append(text + System.lineSeparator());

        try {
            //4.发送
            bw.write(text);
            bw.newLine();
            bw.flush();
            //5.清空文本框内容
            jtf.setText("");

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

  

 

 

  




 

posted @ 2020-07-25 17:06  ASKANDANSWERS  阅读(202)  评论(0编辑  收藏  举报