利用java编写网络聊天程序并加密信息

利用java编写网络聊天程序并加密信息

——————————————————————————————分割线————————
看链接里面的文章,是我重构后代码,比这篇文章的破代码强多了

优化了代码后的地址:https://blog.csdn.net/qq_43483251/article/details/125470514?spm=1001.2014.3001.5501

——————————分割线—————————————

所用知识:javaGUI+网络编程+多线程+信息加密

**原理:**GUI编写基本的图形化界面,利用UDP传输信息,利用多线程同时接收以及发送信息,利用信息加密,加密,密码以及聊天信息。

可能会遇到的问题:

2.javaGUI中的重画方法,repaint只能在原有基础上重绘,并不能清除原来痕迹。因为我使用的Swing默认为轻量级则不执行update,awt组件才是重量级。解决方法:

removeAll()移除组件,repaint()刷新面板,再添加组件( add() ),最后重新布局面板( revalidate() )。

3.只有字符串类型的相同变量的哈希值才会相同,因为字符串都存储在同一内存池中,且每定义一个字符串变量会先判断内存池中是否有相同内容的,如果有就不会开辟新的空间,而是直接将变量指向此内容。

4.网络编程中接收的消息被存储进字节数组中,再次拿出来时其实还附带了空余的字节数组空间中的默认值:0,需要对字节数组做判断并只拿取有效的字符串信息。

代码:

登陆界面代码:

package MyNetworkSecurity01;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.*;

public class Land   {

    //用来当按钮按下后赋值的变量,控制客户端的弹出
    int i=0;
    JFrame frame=new JFrame();
    //设置面板,为了显示标签
    JPanel panel=new JPanel();

    //设置账号,密码的标签
    JLabel land =new JLabel("请登录或者注册!");
    JLabel accountNumber =new JLabel("账号:");
    JLabel password=new JLabel("密码:");

    //设置标签旁的文本框,因为要观察加密情况,所以密码框也使用普通文本框
    JTextField accountNumber02 = new  JTextField(20);
    JTextField password02 = new  JTextField(20);

    //设置登陆和注册按钮!
    JButton landButton= new JButton("登陆");
    JButton registerButton = new JButton("注册");
    //显示登陆成功的标签
    JLabel label = new JLabel( "登陆成功!");
    //登陆成功后跳转的按钮
    JButton Jump=new JButton("继续");
    //构造方法
    Land(){
        //设置界面居中
        frame.setBounds(Toolkit.getDefaultToolkit().getScreenSize().width/2-200,Toolkit.getDefaultToolkit().getScreenSize().height/2-250,400,500);
        //设置程序标题
        frame.setTitle("                      登陆界面");
        //设置关闭
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        //设置容器
        Container container=frame.getContentPane();

        //设置面板的布局
        panel.setLayout(null);
        //将面板放入容器
        container.add(panel);


        //设置标签位置
        land.setBounds(100,25,200,50);
        accountNumber.setBounds(50,75,50,50);
        password.setBounds(49,150,50,50);
        //设置字体的样式:行楷,粗体,大小
        land.setFont(new Font("行楷",Font.BOLD,20));
        accountNumber.setFont(new Font("行楷",Font.BOLD,20));
        password.setFont(new Font("行楷",Font.BOLD,20));
        //将标签放入面板
        panel.add(land);
        panel.add(accountNumber);
        panel.add(password);

        //设置文本框的位置
        accountNumber02.setBounds(100,85,200,30);
        password02.setBounds(99,160,200,30);
        //将文本框放入面板
        panel.add(accountNumber02);
        panel.add(password02);

        //设置按钮的位置和大小
        landButton.setBounds(70,300,80,35);
        registerButton.setBounds(230,300,80,35);
        //将按钮添加进面板
        panel.add(landButton);
        panel.add(registerButton);

        Button_ button_ = new Button_();//创建按钮点击事件实现类的对象
        //设置按钮的监听事件
        //登陆的监听事件
        landButton.addActionListener(button_);
        //注册的监听事件
        registerButton.addActionListener(button_);
        Jump.addActionListener(new Button_01());
        //文本框的事件监听
        //账号框
        accountNumber02.addActionListener(button_);
        //密码框
        password02.addActionListener(button_);

        frame.setVisible(true);
    }

    //用成员内部类实现按钮点击事件
    class  Button_ implements ActionListener  {
        @Override
        public void actionPerformed(ActionEvent e) {

            //获取账号框的内容
            String accountNumber_Button = accountNumber02.getText();
            accountNumber02.setText("");//清空账号框
            //获取密码框内容
            String password_Button = (password02.getText());
            password02.setText("");//清空密码框


            //确认账号,密码输入不为空
            if (accountNumber_Button.equals("") || password_Button.equals("")) {
                JLabel password03 = new JLabel("抱歉,框不能为空!");
                password03.setForeground(Color.red);//设置字体颜色
                password03.setBounds(70, 350, 250, 40);
                password03.setFont(new Font("行楷", Font.BOLD, 20));

                panel.removeAll();//移除组件
                panel.repaint();//刷新移除组件后的效果组件
                //重新添加组件
                panel.add(land);
                panel.add(accountNumber);
                panel.add(password);
                panel.add(accountNumber02);
                panel.add(password02);
                panel.add(landButton);
                panel.add(registerButton);
                panel.add(password03);
                //重新布局面板
                panel.revalidate();

            } else {
                String hashCode_password="";

                //将接收到的密码转换成字符数组进行倒置

                //将获取的密码(字符串)变成字符数组
                char[] hashCode_password01 =password_Button.toCharArray();

                //倒置字符数组并转换成字符串,如:第一个变为最后一个。
                for (int length = hashCode_password01.length-1; length >=0; length--) {
                    hashCode_password=hashCode_password+hashCode_password01[length];
                }

                //计算密码的字符串形式的哈希值,并重新赋值给hashCode_password(字符串变量)
                int i = hashCode_password.hashCode();
                hashCode_password=""+i;

                //处理登陆和注册问题
                if (e.getActionCommand().equals("登陆")) {
                    try {
                        TextSend(accountNumber_Button,hashCode_password);

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

                }

                //设置显示点击按钮后加密后的密码
                JLabel password03 = new JLabel("加密后的密码是:");
                password03.setForeground(Color.red);//设置字体颜色
                password03.setBounds(70, 100, 200, 40);
                password03.setFont(new Font("行楷", Font.BOLD, 20));

                JTextField password_text = new JTextField();//用来显示加密后的密码
                password_text.setBounds(70, 150, 250, 35);
                password_text.setText(""+hashCode_password);


                panel.removeAll();//移除组件
                panel.repaint();//刷新移除组件后的效果组件
                //重新添加组件

                panel.add(password03);
                panel.add(password_text);
                panel.add(label);
                panel.add(Jump);
                //重新布局面板
                panel.revalidate();
            }
        }
    }
    class  Button_01 implements ActionListener{

        @Override
        public void actionPerformed(ActionEvent e1) {
            //设置登陆后的跳转按钮点击事件
            if(e1.getActionCommand().equals("继续")){

                frame.setVisible(false);

                //对信息加密解密的类
                EncryptionAndDecryption ed = new EncryptionAndDecryption();

                    YouClient youClient = new YouClient();
                    //接收
                    Runnable runnable = () -> {//定义自身名字 //定义对方的端口号

                        //建立进程要用的端口
                        DatagramSocket socket = null;
                        try {
                            socket = new DatagramSocket(9100);
                        } catch (SocketException e) {
                            e.printStackTrace();
                        }
                        //  设置一个接收数据的字符串
                        String data;
                        while (true) {
                            //设置一次接收多少的字节byte数据
                            byte[] data_byte = new byte[100];//单位是字节
                            //构造一个 DatagramPacket用于接收长度的数据包 length 。
                            DatagramPacket packet = new DatagramPacket(data_byte, 0, data_byte.length);
                            //接收来自DatagramPacket的数据包
                            try {
                                socket.receive(packet);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }

                            String s3="";
                            //存储接收到的信息
                            char[] s2 = (new String(packet.getData(), 0, packet.getData().length)).toCharArray();
                            for(char s1:s2){
                                if(s1==0)break;
                                s3=s3+s1;
                            }
                            //在界面上显示收到的信息
                            youClient.receive_text01.setText(s3);
                            //解密
                            ed.Decryption(s3);
                            youClient.receive_text02.setText(ed.data02);

                            //获得包裹中的数据
                            data = "服务端:" + " " +ed.data02;
                            if (!data.equals("")) {
                                youClient.str = youClient.str + data + "\n";
                                youClient.ChatBox.setText(youClient.str);
                            }
                            youClient.connect.setText("连接成功!");
                        }
                    };

                    //接收
                    Thread thread = new Thread(runnable);
                    thread.start();

            }
        }
    }
    public static void main(String[] args)  {
        new Land();

    }

    //用来发送登陆请求并接收回执/或者发送消息
    public void TextSend(String accountNumber,String password ) throws IOException {
        //建立端口
        DatagramSocket socket=new DatagramSocket(9090);
        //获取本机地址
        InetAddress inetAddress=InetAddress.getByName("localhost");
        //设置另一个的端口号
        int port=5051;
        //账号和密码的数据
        String account="账号"+accountNumber+"密码"+password;
        //发送数据需要的,数据,地址,端口号
        DatagramPacket packet=new DatagramPacket(account.getBytes(),0,account.getBytes().length,inetAddress,port);
        //打包发送
        socket.send(packet);

        //接收回执
        //接收数据包
        byte[] buffer=new byte[1024];
        //构造一个 DatagramPacket用于接收长度的数据包 length 。
        DatagramPacket packet1=new DatagramPacket(buffer,0,buffer.length);
        //接收来自DatagramPacket的数据包
        socket.receive(packet1);
        String receive = new String(packet1.getData(), 0, "登陆成功!".getBytes().length);
        if(receive.equals("登陆成功!")){
            try {

                label.setBounds(120,190,250,30);
                label.setFont(new Font("行楷", Font.BOLD, 30));
                Jump.setBounds(140,350,100,30);

            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        //关闭流
        socket.close();
    }
}

在这里插入图片描述
在这里插入图片描述

服务端代码:

package MyNetworkSecurity01;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.*;

public class MyServer {

    //用来存储聊天信息
   static String str="";
    //用来接收输入框中的信息
   static String str1="";

    JFrame frame=new JFrame();
    //设置最内层面板
    JPanel panel=new JPanel();
    //设置panel_text聊天面板的组件
    JTextArea ChatBox=new JTextArea(20,10);//文本域,聊天记录显示
    //设置显示对话内容的面板
    JScrollPane panel_text=new JScrollPane(ChatBox);
    //设置容器
    Container container=frame.getContentPane();

    //panel的组件
    JTextField connect = new JTextField();
     //标签
    JLabel receive01=new JLabel("收到的加密信息:");
    JLabel receive02=new JLabel("解译后:");

    JLabel send_out01=new JLabel("想发送的文字:");
    JLabel send_out02=new JLabel("加密后:");
    //文本框
    JTextField receive_text01=new JTextField();
    JTextField receive_text02=new JTextField();

    JTextField send_out_text01=new JTextField();
    JTextField send_out_text02=new JTextField();

    JTextField ChatText=new JTextField();//聊天输入框
    JButton inButton=new JButton("发送"); //发送信息按钮

    public void init(){
        //设置界面居中
        frame.setBounds(Toolkit.getDefaultToolkit().getScreenSize().width/2-300,Toolkit.getDefaultToolkit().getScreenSize().height/2-350,600,700);
        //设置程序标题
        frame.setTitle("服务端");
        //设置关闭
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        //设置面板的布局
        panel.setLayout(null);
        //设置聊天面板的大小,位置
        panel_text.setBounds(200,0,380,500);
        //将面板放入容器
        container.add(panel);
        panel.add(panel_text);

        //设置最内层面板的组件
        connect.setBounds(20,50,150,30);

        receive01.setBounds(20,130,180,30);
        receive01.setFont(new Font("行楷",Font.BOLD,20));
        receive01.setForeground(Color.red);//设置字体颜色
        receive_text01.setBounds(20,160,150,30);
        receive_text01.setFont(new Font("行楷",Font.BOLD,20));

        receive02.setBounds(20,190,150,30);
        receive02.setFont(new Font("行楷",Font.BOLD,20));
        receive02.setForeground(Color.red);
        receive_text02.setBounds(20,220,150,30);
        receive_text02.setFont(new Font("行楷",Font.BOLD,20));


        send_out01.setBounds(20,300,150,30);
        send_out01.setFont(new Font("行楷",Font.BOLD,20));
        send_out01.setForeground(Color.blue);//设置字体颜色
        send_out_text01.setBounds(20,330,150,30);
        send_out_text01.setFont(new Font("行楷",Font.BOLD,20));


        send_out02.setBounds(20,360,150,30);
        send_out02.setFont(new Font("行楷",Font.BOLD,20));
        send_out02.setForeground(Color.blue);//设置字体颜色
        send_out_text02.setBounds(20,390,150,30);
        send_out_text02.setFont(new Font("行楷",Font.BOLD,20));


        //聊天输入框设置
        ChatText.setBounds(200,500,300,30);
        //聊天框的发送按钮
        inButton.setBounds(500,500,100,30);

        //聊天域的字体,大小设置
        ChatBox.setFont(new Font("行楷",Font.BOLD,20));

        panel.add(connect);

        panel.add(receive01);
        panel.add(receive_text01);

        panel.add(receive02);
        panel.add(receive_text02);

        panel.add(send_out01);
        panel.add(send_out_text01);

        panel.add(send_out02);
        panel.add(send_out_text02);

        panel.add(ChatText);
        panel.add(inButton);

        frame.setVisible(true);

        //发送按钮的监听事件
        inButton.addActionListener(new InButton());
    }

    //成员内部类实现接口且发发送数据
     class InButton implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {

            //获取聊天输入框的内容
            str1 = ChatText.getText();
            ChatText.setText("");
            str=str+"我: "+str1+"\n";
            ChatBox.setText(str);

            //加密前的信息到界面显示
            send_out_text01.setText(str1);


            //对信息加密解密的类
            EncryptionAndDecryption ed = new EncryptionAndDecryption();
            //加密
            ed.Encryption(str1);
            //  将加密后的信息发送到界面显示
            send_out_text02.setText(ed.data01);

            try {
                new UDP_Send(5656, 9100,ed.data01);
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }

    //处理登陆或者注册问题
    public void landAndRegister() throws IOException {
        //在本机地址上建立端口,以接收
        DatagramSocket socket=new DatagramSocket(5051);
        //接收数据包
        byte[] buffer=new byte[1024];
        //构造一个 DatagramPacket用于接收长度的数据包 length 。
        DatagramPacket packet=new DatagramPacket(buffer,0,buffer.length);
        //接收来自DatagramPacket的数据包
        socket.receive(packet);
        System.out.println("发送的内容:"+new String(packet.getData(),0,packet.getData().length));

        if(packet.getData()!=null){
            connect.setText("连接成功!");
            //获取本机地址
            InetAddress inetAddress= InetAddress.getByName("localhost");
            int port=9090;
            //参数:数据(Byte类型),发送数据的长度,要发给谁
            DatagramPacket packet1=new DatagramPacket("登陆成功!".getBytes(),0,"登陆成功!".getBytes().length,inetAddress,port);
            socket.send(packet1);//发送包
        }

        //关闭流
        socket.close();
    }


    MyServer( ) throws IOException {
       init();
       landAndRegister();

    }

    public static void main(String[] args) throws IOException {
        MyServer myServer = new MyServer();
        //对信息加密解密的类
        EncryptionAndDecryption ed = new EncryptionAndDecryption();

        //接收
        Runnable runnable = () -> {//定义自身名字 //定义自己的端口号

            //建立进程要用的端口
            DatagramSocket socket = null;
            try {
                socket = new DatagramSocket(5052);
            } catch (SocketException e) {
                e.printStackTrace();
            }
            //  设置一个接收数据的字符串
             String data;
            while (true) {
                //设置一次接收多少的字节byte数据
                byte[] data_byte = new byte[100];//单位是字节
                //构造一个 DatagramPacket用于接收长度的数据包 length 。
                DatagramPacket packet = new DatagramPacket(data_byte, 0, data_byte.length);
                //接收来自DatagramPacket的数据包
                try {
                    socket.receive(packet);
                } catch (IOException e) {
                    e.printStackTrace();
                }

                //因为接收的信息的字节数组长度很长,除了信息外还有很多无用的默认值为:0
                //的数据在数组中,需要加以判断,哪些是有用的,如果不进行判断,输出来的信息
                //会带很长的正方形的小尾巴
                String s3="";
                //存储接收到的信息
                char[] s2 = (new String(packet.getData(), 0, packet.getData().length)).toCharArray();
                for(char s1:s2){
                    if(s1==0)break;
                    s3=s3+s1;
                }

                //在界面上显示收到的信息
                myServer.receive_text01.setText(s3);
                //解密
                ed.Decryption(s3);
                myServer.receive_text02.setText(ed.data02);
                //设置显示在文本域中的信息
                data = "客户端:" + " "+ ed.data02;
                if (!data.equals("")) {
                    str = str + data + "\n";
                    myServer.ChatBox.setText(str);
                }
            }

        };
        //接收
        Thread thread = new Thread(runnable);
        thread.start();


    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nS36lNXY-1599382060840)(image-20200906164337302.png)]

客户端代码:

package MyNetworkSecurity01;

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

public class YouClient {

    //用来存储聊天信息
   static String str="";
    //用来接收输入框中的信息
   static String str1="";

    JFrame frame=new JFrame();
    //设置最内层面板
    JPanel panel=new JPanel();
    //设置panel_text聊天面板的组件
    JTextArea ChatBox=new JTextArea(20,10);//文本域,聊天记录显示
    //设置显示对话内容的面板
    JScrollPane panel_text=new JScrollPane(ChatBox);
    //设置容器
    Container container=frame.getContentPane();

    //panel的组件
    JTextField connect = new JTextField();
    //标签
    JLabel receive01=new JLabel("收到的加密信息:");
    JLabel receive02=new JLabel("解译后:");

    JLabel send_out01=new JLabel("想发送的文字:");
    JLabel send_out02=new JLabel("加密后:");
    //文本框
    JTextField receive_text01=new JTextField();
    JTextField receive_text02=new JTextField();

    JTextField send_out_text01=new JTextField();
    JTextField send_out_text02=new JTextField();

    JTextField ChatText=new JTextField();//聊天输入框
    JButton inButton=new JButton("发送"); //发送信息按钮

    public void init(){
        //设置界面居中
        frame.setBounds(Toolkit.getDefaultToolkit().getScreenSize().width/2-300,Toolkit.getDefaultToolkit().getScreenSize().height/2-350,600,700);
        //设置程序标题
        frame.setTitle("客户端");
        //设置关闭
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        //设置面板的布局
        panel.setLayout(null);
        //设置聊天面板的大小,位置
        panel_text.setBounds(200,0,380,500);
        //将面板放入容器
        container.add(panel);
        panel.add(panel_text);

        //设置最内层面板的组件
        connect.setBounds(20,50,150,30);

        receive01.setBounds(20,130,180,30);
        receive01.setFont(new Font("行楷",Font.BOLD,20));
        receive01.setForeground(Color.red);//设置字体颜色
        receive_text01.setBounds(20,160,150,30);
        receive_text01.setFont(new Font("行楷",Font.BOLD,20));

        receive02.setBounds(20,190,150,30);
        receive02.setFont(new Font("行楷",Font.BOLD,20));
        receive02.setForeground(Color.red);
        receive_text02.setBounds(20,220,150,30);
        receive_text02.setFont(new Font("行楷",Font.BOLD,20));

        send_out01.setBounds(20,300,150,30);
        send_out01.setFont(new Font("行楷",Font.BOLD,20));
        send_out01.setForeground(Color.blue);//设置字体颜色
        send_out_text01.setBounds(20,330,150,30);
        send_out_text01.setFont(new Font("行楷",Font.BOLD,20));

        send_out02.setBounds(20,360,150,30);
        send_out02.setFont(new Font("行楷",Font.BOLD,20));
        send_out02.setForeground(Color.blue);//设置字体颜色
        send_out_text02.setBounds(20,390,150,30);
        send_out_text02.setFont(new Font("行楷",Font.BOLD,20));

        //聊天输入框设置
        ChatText.setBounds(200,500,300,30);
        //聊天框的发送按钮
        inButton.setBounds(500,500,100,30);

        //聊天域的字体,大小设置
        ChatBox.setFont(new Font("行楷",Font.BOLD,20));

        panel.add(connect);

        panel.add(receive01);
        panel.add(receive_text01);

        panel.add(receive02);
        panel.add(receive_text02);

        panel.add(send_out01);
        panel.add(send_out_text01);

        panel.add(send_out02);
        panel.add(send_out_text02);

        panel.add(ChatText);
        panel.add(inButton);

        frame.setVisible(true);
        //发送按钮的监听事件
        inButton.addActionListener(new InButton());
    }
    //成员内部类实现接口且发发送数据
    class InButton implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            //获取聊天输入框的内容
            str1 = ChatText.getText();
            send_out_text01.setText(str1);
            //对信息加密解密的类
            EncryptionAndDecryption ed = new EncryptionAndDecryption();
            //加密
            ed.Encryption(str1);
            //  将加密后的信息发送到界面显示
            send_out_text02.setText(ed.data01);
            ChatText.setText("");
            str=str+"我: "+str1+"\n";
            ChatBox.setText(str);
            try {
                new UDP_Send(9099, 5052,ed.data01);
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }
    YouClient(){
        init();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L9ORLtiv-1599382060843)(image-20200906164426005.png)]

UDP发送代码:

package MyNetworkSecurity01;

import java.io.IOException;
import java.net.*;

//发送
public class UDP_Send {
    //定义对方的端口号
    public int MyPort,YouPort;

    //建立进程要用的端口
    DatagramSocket socket=new DatagramSocket(MyPort);
    //获取本机ip
    InetAddress inetAddress= InetAddress.getByName("localhost");
    //要传输的数据
    private String data;

    public UDP_Send(int MyPort,int YouPort,String data) throws IOException {
       this.MyPort=MyPort;
       this.YouPort=YouPort;
        this.data=data;
        if(!this.data.equals("")) {
            //准备好要发的数据,目的地的ip地址,进程端口号
            DatagramPacket packet = new DatagramPacket(this.data.getBytes(), 0, this.data.getBytes().length, inetAddress, this.YouPort);
            //发送
            try {
                socket.send(packet);
            } catch (IOException e) {
                e.printStackTrace();
            }
            socket.close();
            this.data="";//清空要传输的数据数据
        }
    }
}

加密与解密代码:

package MyNetworkSecurity01;

import java.util.Random;

public class EncryptionAndDecryption {
    //设置接收最终加密后信息的字符串变量
    String data01="";
    //设置接收最终解密后信息的字符串变量
    String data02="";
    //加密
    public  void Encryption(String encryption){
        data01="";
        Random r=new Random();
        //随机取0-10一个数作为偏移量
        int Offset01 =r.nextInt(10);
        //将需要加密的字符串变为字符数组,并且将偏移量作为字符数组的第一个数
        char[] char01=(Offset01+encryption).toCharArray();
        /*加入在字符数组的每个数中加入偏移量,使之改变为其他数,
        如:a+3(3为偏移量)=d,这样加密了信息
         */
        for (int i = 0; i < char01.length; i++) {
            data01=data01+(char) ((int)char01[i]+Offset01);
        }
    }
    //解密
    public  void Decryption(String decryption){
        data02="";

        //将得到的信息变成字符数组
        char[] char02 = decryption.toCharArray();

        //获取偏移量
        int Offset02= ((int)char02[0]-48)/2;

        //利用循环和偏移量解出信息,并保存在字符数组中
        for(int i=1;i<char02.length;i++){
            data02=data02+(char) (char02[i]-Offset02);
        }
    }

}
先运行safechat包里的greetigserver.class,之后运行greetingclient.class即可。 如遇报错,请参考:https://blog.csdn.net/fengzun_yi/article/details/104497160 实现过程: 1. 采用TCP通信协议完成接收者发送者双方的消息传递。 2. 利用Diffie-Hellman密钥交换协议生成对称加密通信的通信密钥。 3. 为防止中间人攻击,采用RSA非对称加密算法协助DH算法完成密钥交换。具体过程如下: a. 接收者与发送者双方各自利用RSA算法生成自己的公私钥,并生成数字证书,并在一个CA进行认证。 b. 在DH密钥交换阶段,A生成A的DH协商密钥用于发送给B,该密钥与接收方私钥生成最终通信密钥。发送DH密钥时,A先用自己的私钥加密DH协商密钥,再去CA获得一个真实的B的公钥,用B的公钥对加密过的协商密钥再做一次加密,发送给B。(因为是用B的公钥加密过,只有B有B的私钥,所以接收信息只有B自己可以解密查看,又因为是用A的私钥加密过的,只有A有A的私钥,所以只有用A的公钥可以进行解密,所以可以保证协商密钥确实是A发送过来的,而且发送的信息也无法被中间人解密。)B收到信息之后,先用自己的私钥解密,然后去CA获得A的公钥再对消息解密一次,获得A的DH密钥。B发给A的过程同上。 c. 之后双方执行DH生成本地密钥的过程。A利用B发送过来的密钥和A的DH私钥生成通信密钥。B利用A发送过来的密钥和B的DH私钥生成通信密钥。根据DH原理,两者生成的通信密钥是相同的。 4. 利用上一步生成的通信密钥,采用AES对称加密算法进行加密通信。 为了方便起见,并没用对A和B双方进行颁发证书的操作,A的公钥默认B已经从CA获得,B的公钥默认A已经从CA获得。并且采用java控制台交互,仅仅为演示原理及简单效果。
Java聊天程序 需求分析 2.1 业务需求 1. 与聊天室成员一起聊天。 2. 可以与聊天室成员私聊。 3. 可以改变聊天内容风格。 4. 用户注册(含头像)、登录。 5. 服务器监控聊天内容。 6. 服务器过滤非法内容。 7. 服务器发送通知。 8. 服务器踢人。 9. 保存服务器日志。 10.保存用户聊天信息。 2.2 系统功能模块 2.2.1 服务器端 1.处理用户注册 2.处理用户登录 3.处理用户发送信息 4.处理用户得到信息 5.处理用户退出 2.2.2 客户端 1.用户注册界面及结果 2.用户登录界面及结果 3.用户发送信息界面及结果 4.用户得到信息界面及结果 5.用户退出界面及结果 2.3 性能需求 运行环境:Windows 9x、2000、xp、2003,Linux 必要环境:JDK 1.5 以上 硬件环境:CPU 400MHz以上,内存64MB以上 3.1.2 客户端结构 ChatClient.java 为客户端程序启动类,负责客户端的启动和退出。 Login.java 为客户端程序登录界面,负责用户帐号信息的验证与反馈。 Register.java 为客户端程序注册界面,负责用户帐号信息的注册验证与反馈。 ChatRoom.java 为客户端程序聊天室主界面,负责接收、发送聊天内容与服务器端的Connection.java 亲密合作。 Windowclose 为ChatRoom.java的内部类,负责监听聊天室界面的操作,当用户退出时返回给服务器信息。 Clock.java 为客户端程序的一个小程序,实现的一个石英钟功能。 3. 2 系统实现原理 当用户聊天时,将当前用户名、聊天对象、聊天内容、聊天语气和是否私聊进行封装,然后与服务器建立Socket连接,再用对象输出流包装Socket的输出流将聊天信息对象发送给服务器端 当用户发送聊天信息时,服务端将会收到客户端用Socket传输过来的聊天信息对象,然后将其强制转换为Chat对象,并将本次用户的聊天信息对象添加到聊天对象集Message中,以供所有聊天用户访问。 接收用户的聊天信息是由多线程技术实现的,因为客户端必须时时关注更新服务器上是否有最新消息,在本程序中设定的是3秒刷新服务器一次,如果间隔时间太短将会增加客户端与服务器端的通信负担,而间隔时间长就会让人感觉没有时效性,所以经过权衡后认为3秒最佳,因为每个用户都不可能在3秒内连续发送信息。 当每次用户接收到聊天信息后将会开始分析聊天信息然后将适合自己的信息人性化地显示在聊天信息界面上。 4.1.1 问题陈述 1.接受用户注册信息并保存在一个基于文件的对象型数据库。 2.能够允许注册过的用户登陆聊天界面并可以聊天。 3.能够接受私聊信息并发送给特定的用户。 4.服务器运行在自定义的端口上#1001。 5.服务器监控用户列表和用户聊天信息(私聊除外)。 6.服务器踢人,发送通知。 7.服务器保存日志。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值