Java网络通信实验小记四:Swing聊天软件

Swing聊天软件

前面做了Tcp和Udp的基本通信以及文件传输实验,是时候把这些内容整合在一起了。。
Swing就不介绍了,需要用到什么api都可以直接查。

一、基本聊天功能(服务端作中介,udp实现)

软件能够实现Windows主机和一台Linux虚拟机的通信。除此之外还需要一台Linux虚拟机作为服务端起到二者中介的作用。两个客户端与服务器的通信采用无连接的udp协议,服务器收到udp包直接向目标端口转发,不做其他任何操作。客户端在发送按钮事件里编写socket.send,同时new一个Thread并在此进程里编写socket.recieve,只有采用多线程才能保证聊天时能够同时收发信息。以上便可实现基本的聊天功能。
注意Win和Linux二者的编码有别。即

//Win客户端
byte[] buffer = text.getBytes("UTF-8");
...
//Linux客户端
byte[] buffer = text.getBytes("GBK");

二、文件传输功能(端到端,tcp实现)

文件传输采用tcp协议直接由端到端传输,这样的好处是传输效率高而且可靠、面向连接。除此之外,还需要多加一个收发信的确认功能。为了避免占用太多端口以及浪费过多线程,这里收发信还是使用原来的udp端口(而不是新建一个端口+线程)。那么就需要设计一个密文放在消息的开头以区分正常的聊天消息(我用的是三个井号"###"也可以更复杂点)。然后该密文还需要携带一些重要信息,包括:文件类型,文件名称,文件大小,主机ip以及端口号,后两者是为了告知目的主机使其与发送主机主动建立tcp连接(因为主机之间是不知道对方的ip和端口号的)。
文件传输的基本设计思路为:
发端:点击文件按钮→选择文件,获取文件、文件名等,发送密文,打开serversocket等待对方accept。
收端:收到udp消息,进行解析发现是密文,于是弹出对话框问是否接受。若选否则进行tcp连接,发送"no"消息,关闭socket。若选是则也进行tcp连接,发送"yes"消息,并准备接收文件。
发端:连接成功后,收到"no"则关闭连接,收到"yes"则准备发送文件。若是图片则使用字节流方法,文本文件则使用字符流方法。
其中传文本文件还要注意一下中文编码问题。在发端读取文件时,Win使用GBK编码,Linux使用UTF-8编码。在收端读取socket的inputStream时二者均使用UTF-8编码。

实验截图:
在这里插入图片描述

三、代码

1.Win客户端代码(ip:10.177.26.76,udp port:1080,tcp port:2080)

package gui;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;

public class WinClient
{
    public static void main(String[] args) throws Exception
    {
        JFrame f = new JFrame();
        f.setTitle("16010410031 陈大至");

        f.setSize(720, 810);
        f.setLocation(100, 100);
        f.setLayout(null);

        JButton button = new JButton("发送");
        button.setBounds(610, 650, 80, 50);
        f.add(button);
        JButton imgButton = new JButton("图片");
        imgButton.setBounds(10,560,70,30);
        f.add(imgButton);
        JButton fileButton = new JButton("文本文件");
        fileButton.setBounds(100,560,90,30);
        f.add(fileButton);

        JTextArea textArea1 = new JTextArea();
        textArea1.setFont(new Font("Dialog", Font.TRUETYPE_FONT,20));
        textArea1.setLineWrap(true);
        textArea1.setBounds(10, 600, 590, 150);
        f.add(textArea1);

        JTextArea textArea2 = new JTextArea();
        textArea2.setFont(new Font("Dialog", Font.TRUETYPE_FONT,20));
        textArea2.setEditable(false);
        textArea2.setLineWrap(true);
        JScrollPane scrollPane = new JScrollPane(textArea2);
        f.add(scrollPane);
        textArea2.setBounds(10,10, 680, 540);
        f.add(textArea2);

        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);

        String hostname="192.168.131.135";//192.168.131.135
        String localhost="10.177.26.76";
        DatagramSocket socket1 = new DatagramSocket(1080);
        ServerSocket socket2 = new ServerSocket(2080);
        new Thread(() -> {
            while (true)
            {
                try {
                    byte[] buffer = new byte[1024];
                    DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
                    socket1.receive(packet);
                    String text = new String(packet.getData(),0,packet.getLength());
                    String[] strings = text.split(";");
                    if(strings[0].equals("###"))
                    {
                        int option;
                        String name=strings[2];
                        String length=strings[3];
                        String ip=strings[4];
                        int port=Integer.parseInt(strings[5]);
                        option = JOptionPane.showConfirmDialog(f,"收到文件:"+name+",大小:"+length+"kb,是否接收?");
                        Socket socket = new Socket(ip,port);
                        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                        if(strings[1].equals("img"))
                        {
                            if(option==JOptionPane.OK_OPTION)
                            {
                                out.println("yes");
                                InputStream in = socket.getInputStream();
                                FileOutputStream fileOut = new FileOutputStream("statics/保存图片.png");
                                byte[] bytes = new byte[1024];
                                int len;
                                while((len = in.read(bytes))!=-1){
                                    fileOut.write(bytes, 0, len);
                                }
                                JOptionPane.showMessageDialog(f,"文件接收成功。路径:statics/保存图片.png");
                                fileOut.close();
                                in.close();
                            }
                            else
                            {
                                out.println("no");
                                JOptionPane.showMessageDialog(f,"已取消接受文件。");
                            }
                        }
                        else if(strings[1].equals("file"))
                        {
                            if(option==JOptionPane.OK_OPTION)
                            {
                                out.println("yes");
                                BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(),Charset.forName("UTF-8")));
                                PrintWriter fileOut = new PrintWriter("statics/"+name);
                                String s;
                                while((s = in.readLine())!=null)
                                {
                                    System.out.println(s);
                                    fileOut.println(s);
                                }
                                fileOut.close();
                                in.close();
                                JOptionPane.showMessageDialog(f,"文件接收成功。路径:statics/"+name);
                            }
                            else
                            {
                                out.println("no");
                                JOptionPane.showMessageDialog(f,"已取消接受文件。");
                            }
                        }
                        out.close();
                        socket.close();
                    }
                    else textArea2.append("对方:"+text+"\r\n");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        button.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                String text = textArea1.getText();
                textArea2.append("你:"+text+"\r\n");
                try {
                    byte[] buffer = text.getBytes("UTF-8");
                    DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName(hostname),1082);
                    socket1.send(packet);
                    textArea1.setText("");
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        });
        imgButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                try{
                    JFileChooser fileChooser = new JFileChooser();
                    fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
                    fileChooser.setCurrentDirectory(new File("D:\\"));
                    fileChooser.setFileFilter(new FileNameExtensionFilter("Image Files","png","jpg","gif"));
                    int result = fileChooser.showOpenDialog(f);
                    if(result==JFileChooser.APPROVE_OPTION)
                    {
                        File file = fileChooser.getSelectedFile();
                        String filename = file.getName();
                        Long length = file.length()/1024;
                        String message = "###;img;"+filename+";"+length.toString()+";"+localhost+";2080";
                        byte[] buffer = message.getBytes();
                        DatagramPacket packet = new DatagramPacket(buffer,buffer.length,InetAddress.getByName(hostname),1082);
                        socket1.send(packet);
                        Socket socket = socket2.accept();
                        System.out.println("TCP连接成功");
                        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        if(reader.readLine().equals("yes"))
                        {
                            FileInputStream fileIn = new FileInputStream(file);
                            OutputStream out = socket.getOutputStream();
                            byte[] bytes = new byte[1024];
                            int len;
                            while((len = fileIn.read(bytes))!= -1)
                            {
                                out.write(bytes, 0, len);
                            }
                            JOptionPane.showMessageDialog(f,"文件传输成功。");
                            fileIn.close();
                            out.close();
                        }
                        else
                        {
                            JOptionPane.showMessageDialog(f,"文件被对方拒收。");
                        }
                        reader.close();
                        socket.close();
                    }
                }catch (Exception e1){
                    e1.printStackTrace();
                }
            }
        });
        fileButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                try{
                    JFileChooser fileChooser = new JFileChooser();
                    fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
                    fileChooser.setCurrentDirectory(new File("D:\\"));
                    fileChooser.setFileFilter(new FileNameExtensionFilter("Text Files","txt","doc","xls"));
                    int result = fileChooser.showOpenDialog(f);
                    if(result==JFileChooser.APPROVE_OPTION)
                    {
                        File file = fileChooser.getSelectedFile();
                        String filename = file.getName();
                        Long length = file.length()/1024;
                        String message = "###;file;"+filename+";"+length.toString()+";"+localhost+";2080";
                        byte[] buffer = message.getBytes();
                        DatagramPacket packet = new DatagramPacket(buffer,buffer.length,InetAddress.getByName(hostname),1082);
                        socket1.send(packet);
                        Socket socket = socket2.accept();
                        System.out.println("TCP连接成功");
                        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        if(reader.readLine().equals("yes"))
                        {
                            BufferedReader fileIn = new BufferedReader(new InputStreamReader(new FileInputStream(file), Charset.forName("GBK")));
                            PrintWriter out = new PrintWriter(socket.getOutputStream(),true);
                            String s;
                            while((s = fileIn.readLine())!=null)
                            {
                                System.out.println(s);
                                out.println(s);
                            }
                            JOptionPane.showMessageDialog(f,"文件传输成功。");
                            fileIn.close();
                            out.close();
                        }
                        else
                        {
                            JOptionPane.showMessageDialog(f,"文件被对方拒收。");
                        }
                        reader.close();
                        socket.close();
                    }
                }catch (Exception e1){
                    e1.printStackTrace();
                }
            }
        });
    }
}

2.Linux客户端代码(ip:192.168.131.131,udp port:1081,tcp port:2081)

package gui;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.*;
import java.nio.charset.Charset;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;

public class LinuxClient
{
    public static void main(String[] args) throws Exception
    {
        JFrame f = new JFrame();
        f.setTitle("16010410031 陈大至");

        f.setSize(700, 790);
        f.setLocation(900, 100);
        f.setLayout(null);

        JButton button = new JButton("发送");
        button.setBounds(610, 650, 80, 50);
        f.add(button);
        JButton imgButton = new JButton("图片");
        imgButton.setBounds(10,560,70,30);
        f.add(imgButton);
        JButton fileButton = new JButton("文本文件");
        fileButton.setBounds(100,560,90,30);
        f.add(fileButton);

        JTextArea textArea1 = new JTextArea();
        textArea1.setFont(new Font("Dialog", Font.TRUETYPE_FONT,20));
        textArea1.setLineWrap(true);
        textArea1.setBounds(10, 600, 590, 150);
        f.add(textArea1);

        JTextArea textArea2 = new JTextArea();
        textArea2.setFont(new Font("Dialog", Font.TRUETYPE_FONT,20));
        textArea2.setEditable(false);
        textArea2.setLineWrap(true);
        JScrollPane scrollPane = new JScrollPane(textArea2);
        f.add(scrollPane);
        textArea2.setBounds(10,10, 680, 540);
        f.add(textArea2);

        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);

        String hostname = "192.168.131.135";//192.168.131.135
        String localhost="192.168.131.131";//192.168.131.131
        DatagramSocket socket1 = new DatagramSocket(1081);
        ServerSocket socket2 = new ServerSocket(2081);
        new Thread(() -> {
            while (true)
            {
                try {
                    byte[] buffer = new byte[1024];
                    DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
                    socket1.receive(packet);
                    String text = new String(packet.getData(),0,packet.getLength());
                    String[] strings = text.split(";");
                    if(strings[0].equals("###"))
                    {
                        int option;
                        String name=strings[2];
                        String length=strings[3];
                        String ip=strings[4];
                        int port=Integer.parseInt(strings[5]);
                        option = JOptionPane.showConfirmDialog(f,"收到文件:"+name+",大小:"+length+"kb,是否接收?");
                        Socket socket = new Socket(ip,port);
                        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                        if(strings[1].equals("img"))
                        {
                            if(option==JOptionPane.OK_OPTION)
                            {
                                out.println("yes");
                                InputStream inputStream = socket.getInputStream();
                                FileOutputStream fileOut = new FileOutputStream("statics/保存图片.png");
                                byte[] bytes = new byte[1024];
                                int len;
                                while((len = inputStream.read(bytes))!=-1){
                                    fileOut.write(bytes, 0, len);
                                }
                                JOptionPane.showMessageDialog(f,"文件接收成功。路径:statics/保存图片.png");
                                fileOut.close();
                                socket.close();
                            }
                            else
                            {
                                out.println("no");
                                JOptionPane.showMessageDialog(f,"已取消接受文件。");
                                socket.close();
                            }
                        }
                        else if(strings[1].equals("file"))
                        {
                            if(option==JOptionPane.OK_OPTION)
                            {
                                out.println("yes");
                                BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(),Charset.forName("UTF-8")));
                                PrintWriter fileOut = new PrintWriter("statics/"+name);
                                String s;
                                while((s = in.readLine())!=null)
                                {
                                    System.out.println(s);
                                    fileOut.println(s);
                                }
                                fileOut.close();
                                in.close();
                                JOptionPane.showMessageDialog(f,"文件接收成功。路径:statics/"+name);
                            }
                            else
                            {
                                out.println("no");
                                JOptionPane.showMessageDialog(f,"已取消接受文件。");
                            }
                        }
                        out.close();
                        socket.close();
                    }
                    else textArea2.append("对方:"+text+"\r\n");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        button.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                String text = textArea1.getText();
                textArea2.append("你:"+text+"\r\n");
                try {
                    byte[] buffer = text.getBytes("GBK");
                    DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName(hostname),1082);
                    socket1.send(packet);
                    textArea1.setText("");
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        });
        imgButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                try{
                    JFileChooser fileChooser = new JFileChooser();
                    fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
                    fileChooser.setCurrentDirectory(new File("."));
                    fileChooser.setFileFilter(new FileNameExtensionFilter("Image Files","png","jpg","gif"));
                    int result = fileChooser.showOpenDialog(f);
                    if(result==JFileChooser.APPROVE_OPTION)
                    {
                        File file = fileChooser.getSelectedFile();
                        String filename = file.getName();
                        Long length = file.length()/1024;
                        String message = "###;img;"+filename+";"+length.toString()+";"+localhost+";2081";
                        byte[] buffer = message.getBytes();
                        DatagramPacket packet = new DatagramPacket(buffer,buffer.length,InetAddress.getByName(hostname),1082);
                        socket1.send(packet);
                        Socket socket = socket2.accept();
                        System.out.println("TCP连接成功");
                        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        if(reader.readLine().equals("yes"))
                        {
                            FileInputStream fileIn = new FileInputStream(file);
                            OutputStream out = socket.getOutputStream();
                            byte[] bytes = new byte[1024];
                            int len;
                            while((len = fileIn.read(bytes))!= -1)
                            {
                                out.write(bytes, 0, len);
                            }
                            JOptionPane.showMessageDialog(f,"文件传输成功。");
                            fileIn.close();
                            out.close();
                        }
                        else
                        {
                            JOptionPane.showMessageDialog(f,"文件被对方拒收。");
                        }
                        reader.close();
                        socket.close();
                    }
                }catch (Exception e1){
                    e1.printStackTrace();
                }
            }
        });
        fileButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                try{
                    JFileChooser fileChooser = new JFileChooser();
                    fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
                    fileChooser.setCurrentDirectory(new File("."));
                    fileChooser.setFileFilter(new FileNameExtensionFilter("Text Files","txt","doc","xls"));
                    int result = fileChooser.showOpenDialog(f);
                    if(result==JFileChooser.APPROVE_OPTION)
                    {
                        File file = fileChooser.getSelectedFile();
                        String filename = file.getName();
                        Long length = file.length()/1024;
                        String message = "###;file;"+filename+";"+length.toString()+";"+localhost+";2081";
                        byte[] buffer = message.getBytes();
                        DatagramPacket packet = new DatagramPacket(buffer,buffer.length,InetAddress.getByName(hostname),1082);
                        socket1.send(packet);
                        Socket socket = socket2.accept();
                        System.out.println("TCP连接成功");
                        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        if(reader.readLine().equals("yes"))
                        {
                            BufferedReader fileIn = new BufferedReader(new InputStreamReader(new FileInputStream(file), Charset.forName("UTF-8")));
                            PrintWriter out = new PrintWriter(socket.getOutputStream(),true);
                            String s;
                            while((s = fileIn.readLine())!=null)
                            {
                                System.out.print(s);
                                out.println(s);
                            }
                            JOptionPane.showMessageDialog(f,"文件传输成功。");
                            fileIn.close();
                            out.close();
                        }
                        else
                        {
                            JOptionPane.showMessageDialog(f,"文件被对方拒收。");
                        }
                        reader.close();
                        socket.close();
                    }
                }catch (Exception e1){
                    e1.printStackTrace();
                }
            }
        });
    }
}

3.Linux服务器代码(ip:192.168.131.135,udp port:1082)

package gui;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class Server
{
    public static void main(String[] args) throws Exception
    {
        String hostname="",text;
        DatagramSocket socket = new DatagramSocket(1082);
        while(true)
        {
            byte[] buffer = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
            socket.receive(packet);
            text = new String(packet.getData(),0,packet.getLength());
            int port = packet.getPort();
            System.out.print("端口号:"+port+",");
            if(port==1080){
                System.out.println("来自Win主机:"+text);
                port=1081;
                hostname="192.168.131.131";//192.168.131.131
            }
            else if(port==1081){
                System.out.println("来自Ubuntu主机:"+text);
                port=1080;
                hostname="10.177.26.76";
            }
            else System.out.println("端口号错误");
            DatagramPacket packet2 = new DatagramPacket(packet.getData(), packet.getLength(), InetAddress.getByName(hostname),port);
            socket.send(packet2);
        }
    }
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值