简易QQ聊天代码及分析

项目结构目录

结构目录图片

服务端代码

package cn.itcast.chat;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;


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;
    //使用静态代码块进行加载配置文件,并初始化serverPort
    //静态代码块:类加载的时候执行,只执行一次
    static{
        Properties prop = new Properties();
        try {
            prop.load(new FileReader("chat.properties"));
            serverPort = Integer.parseInt(prop.getProperty("serverPort"));
        }catch (Exception e) {
            e.printStackTrace();
        }
    }


    //在构造方法中初始化组件
    public ServerChat(){
        //初始化组件
        //设置文本域默认不可编辑
        jta=new JTextArea();
        jta.setEditable(false);
        //将文本域加入到滚动条中
        jsp=new JScrollPane(jta);
        jp = new JPanel();
        jtf=new JTextField(10);
        jb=new JButton("发送");

        //将文本框与按钮添加到面板中
        jp.add(jtf);
        jp.add(jb);
        //将滚动条和面板添加到窗体中,this代表当前窗体
        this.add(jsp,BorderLayout.CENTER);
        this.add(jp,BorderLayout.SOUTH);
        //设置窗体的一些样式
        this.setTitle("QQ聊天服务端");
        this.setSize(400, 400);
        this.setLocation(200, 200);
        //窗体关闭的时候 ,程序就退出
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);

        /*********************TCP 服务端   start*********************/
        //给发送按钮添加监听点击事件
        jb.addActionListener(this);
        //给文本框添加键盘监听事件
        jtf.addKeyListener(this);
        try {
            //1、创建一个服务端Socket套接字
            ServerSocket serverSocket = new ServerSocket(serverPort);
            //2、等待客户端连接
            Socket socket = serverSocket.accept();
            //3、获取Socket通道的输入流
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            //4、获取Socket通道的输出流(当点击发送的时候才需要输出数据)
            bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

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

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

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

    @Override
    public void actionPerformed(ActionEvent e) {
        sendMsg();
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode()==KeyEvent.VK_ENTER){
            sendMsg();
        }
    }
    //定义一个方法,让其向Socket通道中发送数据
    public void sendMsg(){
        //1、获取文本框中发送的内容
        String text = jtf.getText();
        //2、拼接需要发送的内容给你
        text = "客户端对服务端说:"+text;
        //3、自己也需要显示,这里需要加换行,
        //没有在上面第二步的时候加,是因为加了以后会把换行也会发送出去,bw不能正确读取
        jta.append(text+System.lineSeparator());
        //发送
        try {
            bw.write(text);
            //换行并刷新,否则对方收不到
            bw.newLine();
            bw.flush();
            //清空文本框
            jtf.setText(" ");
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }
    @Override
    public void keyTyped(KeyEvent e) {

    }
    @Override
    public void keyReleased(KeyEvent e) {

    }
}

客户端代码

package cn.itcast.chat;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Properties;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
/**
 * 1、定义JFrame窗口中的组件
 * 2、在构造方法中初始化这些组件
 * 3、使用网络编程完成数据的传输
 * 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;

        //从配置文件中读取客户端IP以及端口号
        private static String clientIP;
        private static int clientPort;
        //使用静态代码块进行加载配置文件,并初始化serverPort
        //静态代码块:类加载的时候执行,只执行一次
        static{
            Properties prop = new Properties();
            try {
                prop.load(new FileReader("chat.properties"));
                clientIP = prop.getProperty("clientIP");
                clientPort = Integer.parseInt(prop.getProperty("clientPort"));
            }catch (Exception e) {
                e.printStackTrace();
            }
        }


        //输出流
        private BufferedWriter bw = null;
        //在构造方法中初始化组件
        public ClientChat(){
            //初始化组件
            //设置文本域默认不可编辑
            jta=new JTextArea();
            jta.setEditable(false);
            //将文本域加入到滚动条中
            jsp=new JScrollPane(jta);
            jp = new JPanel();
            jtf=new JTextField(10);
            jb=new JButton("发送");

            //将文本框与按钮添加到面板中
            jp.add(jtf);
            jp.add(jb);
            //将滚动条和面板添加到窗体中,this代表当前窗体
            this.add(jsp,BorderLayout.CENTER);
            this.add(jp,BorderLayout.SOUTH);
            //设置窗体的一些样式
            this.setTitle("QQ聊天服务端");
            this.setSize(400, 400);
            this.setLocation(600, 200);
            //窗体关闭的时候 ,程序就退出
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.setVisible(true);

            /*********************TCP 客户端   start*********************/
            //给发送按钮添加一个监听点击事件(该类需要实现ActionListener接口)
            jb.addActionListener(this);
            //给文本框添加监听键盘事件(该类实现KeyListener接口)
            jtf.addKeyListener(this);
            try {
                //1、创建一个客户端Socket套接字(尝试连接)
                Socket socket = new Socket(clientIP,clientPort);

                //2、获取Socket通道的输入流
                BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                //3、获取Socket通道的输出流(当点击发送的时候才需要输出数据)
                bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

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

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

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

        @Override
        public void actionPerformed(ActionEvent e) {
            sendMsg();
        }

        @Override
        public void keyPressed(KeyEvent e) {
            if(e.getKeyCode()==KeyEvent.VK_ENTER){
                sendMsg();
            }
        }
        //定义一个方法,让其向Socket通道中发送数据
        public void sendMsg(){
            //1、获取文本框中发送的内容
            String text = jtf.getText();
            //2、拼接需要发送的内容给你
            text = "客户端对服务端说:"+text;
            //3、自己也需要显示,这里需要加换行,
            //没有在上面第二步的时候加,是因为加了以后会把换行也会发送出去,bw不能正确读取
            jta.append(text+System.lineSeparator());
            //发送
            try {
                bw.write(text);
                //换行并刷新,否则对方收不到
                bw.newLine();
                bw.flush();
                //清空文本框
                jtf.setText(" ");
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
        }
        @Override
        public void keyTyped(KeyEvent e) {

        }
        @Override
        public void keyReleased(KeyEvent e) {

        }
}

打包脱离eclipse

首先将ServerChat.java,ClientChat.java分别打包,右击—>export—–>搜索JAR file——>填写导出地址——>next——>next——->填写main class.——–>finish
mainclass

将配置文件与导出的jar包放在同一目录,使用命令提示符运行,即可。
先启动服务端,后启动客户端

//启动服务端
C:\Users\lenovo>cd /d C:\Users\lenovo\Desktop

C:\Users\lenovo\Desktop>java -jar server.jar
//启动客户端
C:\Users\lenovo>cd /d C:\Users\lenovo\Desktop

C:\Users\lenovo\Desktop>java -jar client.jar
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值