Java聊天室之使用Socket實現傳遞圖片

一、題目描述

題目實現:使用網絡編程時,需要通過Socket傳遞圖片。

二、解題思路

創建一個服務器類:ServerSocketFrame,繼承JFrame類

寫一個getserver() 方法,實例化Socket對象,啟用9527當服務的端口。

創建輸入流對象,用來接收客戶端信息。

再定義一個getClientInfo()方法,用於接收客戶端發送的信息。

對文本框添加一個事件:實現向客戶端發磅信息。

創建一個客戶端類:ClientSocketFrame,繼承JFrame類。

寫一個connect() 方法,實例化Socket對象,連接本地服務的9527端口服務。

再定義一個getClientInfo()方法,用於接收服務端發送的信息。

技術重點:

通過使用DataInputStream類的read0方法,將圖片文件讀取到字節數組,然後使用 DataOutputStream類從DataOutput類繼承的write0方法輸出字節數組,從而實現瞭使用Socket傳輸圖片的功能。

三、代碼詳解

ServerSocketFrame

package com.xiaoxuzhu;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.*;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.BevelBorder;
import javax.swing.border.EtchedBorder;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
/**
 * Description: 
 *
 * @author xiaoxuzhu
 * @version 1.0
 *
 * <pre>
 * 修改記錄:
 * 修改後版本	        修改人		修改日期			修改內容
 * 2022/6/4.1	    xiaoxuzhu		2022/6/4		    Create
 * </pre>
 * @date 2022/6/4
 */

public class ServerSocketFrame extends JFrame {
    private Image sendImg = null; // 聲明圖像對象
    private Image receiveImg = null; // 聲明圖像對象
    private SendImagePanel sendImagePanel = null; // 聲明圖像面板對象
    private ReceiveImagePanel receiveImagePanel = null; // 聲明圖像面板對象
    private File imgFile = null;// 聲明所選擇圖片的File對象
    private JTextField tf_path;
    private DataOutputStream out = null; // 創建流對象
    private DataInputStream in = null; // 創建流對象
    private ServerSocket server; // 聲明ServerSocket對象
    private Socket socket; // 聲明Socket對象socket
    private long lengths = -1; // 圖片文件的大小
    public void getServer() {
        try {
            server = new ServerSocket(9527); // 實例化Socket對象
            while (true) { // 如果套接字是連接狀態
                socket = server.accept(); // 實例化Socket對象
                out = new DataOutputStream(socket.getOutputStream());// 獲得輸出流對象
                in = new DataInputStream(socket.getInputStream());// 獲得輸入流對象
                getClientInfo(); // 調用getClientInfo()方法
            }
        } catch (Exception e) {
            e.printStackTrace(); // 輸出異常信息
        }
    }

    private void getClientInfo() {
        try {
            long lengths = in.readLong();// 讀取圖片文件的長度
            byte[] bt = new byte[(int) lengths];// 創建字節數組
            for (int i = 0; i < bt.length; i++) {
                bt[i] = in.readByte();// 讀取字節信息並存儲到字節數組
            }
            receiveImg = new ImageIcon(bt).getImage();// 創建圖像對象
            receiveImagePanel.repaint();// 重新繪制圖像
        } catch (Exception e) {
        } finally {
            try {
                if (in != null) {
                    in.close();// 關閉流
                }
                if (socket != null) {
                    socket.close(); // 關閉套接字
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) { // 主方法
        ServerSocketFrame frame = new ServerSocketFrame(); // 創建本類對象
        frame.setVisible(true);
        frame.getServer(); // 調用方法
    }

    public ServerSocketFrame() {
        super();
        setTitle("服務器端程序");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 379, 260);

        final JPanel panel = new JPanel();
        getContentPane().add(panel, BorderLayout.NORTH);

        final JLabel label = new JLabel();
        label.setText("路徑:");
        panel.add(label);

        tf_path = new JTextField();
        tf_path.setPreferredSize(new Dimension(140, 25));
        panel.add(tf_path);

        sendImagePanel = new SendImagePanel();
        receiveImagePanel = new ReceiveImagePanel();
        final JButton button_1 = new JButton();
        button_1.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {
                JFileChooser fileChooser = new JFileChooser();// 創建文件選擇器
                FileFilter filter = new FileNameExtensionFilter(
                        "圖像文件(JPG/GIF/BMP)", "JPG", "JPEG", "GIF", "BMP");// 創建過濾器
                fileChooser.setFileFilter(filter);// 設置過濾器
                int flag = fileChooser.showOpenDialog(null);// 顯示打開對話框
                if (flag == JFileChooser.APPROVE_OPTION) {
                    imgFile = fileChooser.getSelectedFile(); // 獲取選中圖片的File對象
                }
                if (imgFile != null) {
                    tf_path.setText(imgFile.getAbsolutePath());// 圖片完整路徑
                    try {
                        sendImg = ImageIO.read(imgFile);// 構造BufferedImage對象
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
                sendImagePanel.repaint();// 調用paint()方法
            }
        });
        button_1.setText("選擇圖片");
        panel.add(button_1);

        final JButton button = new JButton();
        button.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {
                try {
                    DataInputStream inStream = null;// 定義數據輸入流對象
                    if (imgFile != null) {
                        lengths = imgFile.length();// 獲得選擇圖片的大小
                        inStream = new DataInputStream(new FileInputStream(imgFile));// 創建輸入流對象
                    } else {
                        JOptionPane.showMessageDialog(null, "還沒有選擇圖片文件。");
                        return;
                    }
                    out.writeLong(lengths);// 將文件的大小寫入輸出流
                    byte[] bt = new byte[(int) lengths];// 創建字節數組
                    int len = -1;
                    while ((len = inStream.read(bt)) != -1) {// 將圖片文件讀取到字節數組
                        out.write(bt);// 將字節數組寫入輸出流
                    }
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        });
        button.setText("發  送");
        panel.add(button);

        final JPanel panel_1 = new JPanel();
        panel_1.setLayout(new BorderLayout());
        getContentPane().add(panel_1, BorderLayout.CENTER);

        final JPanel panel_2 = new JPanel();
        panel_2.setLayout(new GridLayout(1, 0));
        final FlowLayout flowLayout = new FlowLayout();
        flowLayout.setAlignment(FlowLayout.LEFT);
        panel_2.setLayout(flowLayout);
        panel_1.add(panel_2, BorderLayout.NORTH);

        final JLabel label_1 = new JLabel();
        label_1.setBorder(new EtchedBorder(EtchedBorder.LOWERED));
        label_1.setText("服務器端選擇的要發送的圖片  ");
        panel_2.add(label_1);

        final JLabel label_2 = new JLabel();
        label_2.setBorder(new EtchedBorder(EtchedBorder.LOWERED));
        label_2.setText("接收到客戶端發送的圖片       ");
        panel_2.add(label_2);

        final JPanel imgPanel = new JPanel();
        final GridLayout gridLayout = new GridLayout(1, 0);
        gridLayout.setVgap(10);
        imgPanel.setLayout(gridLayout);
        panel_1.add(imgPanel, BorderLayout.CENTER);
        imgPanel.add(sendImagePanel);
        imgPanel.add(receiveImagePanel);
        sendImagePanel.setBorder(new BevelBorder(BevelBorder.LOWERED));
        receiveImagePanel.setBorder(new BevelBorder(BevelBorder.LOWERED));
    }

    // 創建面板類
    class SendImagePanel extends JPanel {
        public void paint(Graphics g) {
            if (sendImg != null) {
                g.clearRect(0, 0, this.getWidth(), this.getHeight());// 清除繪圖上下文的內容
                g.drawImage(sendImg, 0, 0, this.getWidth(), this.getHeight(),
                        this);// 繪制指定大小的圖片
            }
        }
    }

    // 創建面板類
    class ReceiveImagePanel extends JPanel {
        public void paint(Graphics g) {
            if (receiveImg != null) {
                g.clearRect(0, 0, this.getWidth(), this.getHeight());// 清除繪圖上下文的內容
                g.drawImage(receiveImg, 0, 0, this.getWidth(),
                        this.getHeight(), this);// 繪制指定大小的圖片
            }
        }
    }
}

ClientSocketFrame

package com.xiaoxuzhu;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.Socket;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EtchedBorder;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;

/**
 * Description: 
 *
 * @author xiaoxuzhu
 * @version 1.0
 *
 * <pre>
 * 修改記錄:
 * 修改後版本	        修改人		修改日期			修改內容
 * 2022/6/4.1	    xiaoxuzhu		2022/6/4		    Create
 * </pre>
 * @date 2022/6/4
 */

public class ClientSocketFrame extends JFrame {
    private Image sendImg = null; // 聲明圖像對象
    private Image receiveImg = null; // 聲明圖像對象
    private SendImagePanel sendImagePanel = null; // 聲明圖像面板對象
    private ReceiveImagePanel receiveImagePanel = null; // 聲明圖像面板對象
    private File imgFile = null;// 聲明所選擇圖片的File對象
    private JTextField tf_path;
    private DataInputStream in = null; // 創建流對象
    private DataOutputStream out = null; // 創建流對象
    private Socket socket; // 聲明Socket對象
    private Container cc; // 聲明Container對象
    private long lengths = -1;// 圖片文件的大小

    private void connect() { // 連接套接字方法
        try { // 捕捉異常
            socket = new Socket("127.0.0.1", 9527); // 實例化Socket對象
            while (true) {
                if (socket != null && !socket.isClosed()) {
                    out = new DataOutputStream(socket.getOutputStream());// 獲得輸出流對象
                    in = new DataInputStream(socket.getInputStream());// 獲得輸入流對象
                    getServerInfo();// 調用getServerInfo()方法
                } else {
                    socket = new Socket("127.0.0.1", 9527); // 實例化Socket對象
                }
            }
        } catch (Exception e) {
            e.printStackTrace(); // 輸出異常信息
        }
    }

    public static void main(String[] args) { // 主方法
        ClientSocketFrame clien = new ClientSocketFrame(); // 創建本例對象
        clien.setVisible(true); // 將窗體顯示
        clien.connect(); // 調用連接方法
    }

    private void getServerInfo() {
        try {
            long lengths = in.readLong();// 讀取圖片文件的長度
            byte[] bt = new byte[(int) lengths];// 創建字節數組
            for (int i = 0; i < bt.length; i++) {
                bt[i] = in.readByte();// 讀取字節信息並存儲到字節數組
            }
            receiveImg = new ImageIcon(bt).getImage();// 創建圖像對象
            receiveImagePanel.repaint();// 重新繪制圖像
        } catch (Exception e) {
        } finally {
            try {
                if (in != null) {
                    in.close();// 關閉流
                }
                if (socket != null) {
                    socket.close(); // 關閉套接字
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * Create the frame
     */
    public ClientSocketFrame() {
        super();
        setTitle("客戶端程序");
        setBounds(100, 100, 373, 257);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final JPanel panel = new JPanel();
        getContentPane().add(panel, BorderLayout.NORTH);

        final JLabel label = new JLabel();
        label.setText("路徑:");
        panel.add(label);

        tf_path = new JTextField();
        tf_path.setPreferredSize(new Dimension(140, 25));
        panel.add(tf_path);

        final JButton button = new JButton();
        button.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {
                JFileChooser fileChooser = new JFileChooser();// 創建文件選擇器
                FileFilter filter = new FileNameExtensionFilter(
                        "圖像文件(JPG/GIF/BMP)", "JPG", "JPEG", "GIF", "BMP");// 創建過濾器
                fileChooser.setFileFilter(filter);// 設置過濾器
                int flag = fileChooser.showOpenDialog(null);// 顯示打開對話框
                if (flag == JFileChooser.APPROVE_OPTION) {
                    imgFile = fileChooser.getSelectedFile(); // 獲取選中圖片的File對象
                }
                if (imgFile != null) {
                    tf_path.setText(imgFile.getAbsolutePath());// 圖片完整路徑
                    try {
                        sendImg = ImageIO.read(imgFile);// 構造BufferedImage對象
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
                sendImagePanel.repaint();// 調用paint()方法
            }
        });
        button.setText("選擇圖片");
        panel.add(button);

        final JButton button_1 = new JButton();
        button_1.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {
                try {
                    DataInputStream inStream = null;// 定義數據輸入流對象
                    if (imgFile != null) {
                        lengths = imgFile.length();// 獲得選擇圖片的大小
                        inStream = new DataInputStream(new FileInputStream(
                                imgFile));// 創建輸入流對象
                    } else {
                        JOptionPane.showMessageDialog(null, "還沒有選擇圖片文件。");
                        return;
                    }
                    out.writeLong(lengths);// 將文件的大小寫入輸出流
                    byte[] bt = new byte[(int) lengths];// 創建字節數組
                    int len = -1;
                    while ((len = inStream.read(bt)) != -1) {// 將圖片文件讀取到字節數組
                        out.write(bt);// 將字節數組寫入輸出流
                    }
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        });
        button_1.setText("發  送");
        panel.add(button_1);

        final JPanel panel_1 = new JPanel();
        panel_1.setLayout(new BorderLayout());
        getContentPane().add(panel_1, BorderLayout.CENTER);

        final JPanel panel_2 = new JPanel();
        panel_2.setLayout(new GridLayout(1, 0));
        panel_1.add(panel_2, BorderLayout.NORTH);

        final JLabel label_1 = new JLabel();
        label_1.setBorder(new EtchedBorder(EtchedBorder.LOWERED));
        label_1.setText("客戶端選擇的要發送的圖片");
        panel_2.add(label_1);

        final JLabel label_2 = new JLabel();
        label_2.setBorder(new EtchedBorder(EtchedBorder.LOWERED));
        label_2.setText("接收到服務器端發送的圖片     ");
        panel_2.add(label_2);

        final JPanel imgPanel = new JPanel();
        sendImagePanel = new SendImagePanel();
        receiveImagePanel = new ReceiveImagePanel();
        imgPanel.add(sendImagePanel);
        imgPanel.add(receiveImagePanel);
        final GridLayout gridLayout = new GridLayout(1, 0);
        gridLayout.setVgap(6);
        imgPanel.setLayout(gridLayout);
        panel_1.add(imgPanel, BorderLayout.CENTER);
        //
    }

    // 創建面板類
    class SendImagePanel extends JPanel {
        public void paint(Graphics g) {
            if (sendImg != null) {
                g.clearRect(0, 0, this.getWidth(), this.getHeight());// 清除繪圖上下文的內容
                g.drawImage(sendImg, 0, 0, this.getWidth(), this.getHeight(),
                        this);// 繪制指定大小的圖片
            }
        }
    }

    // 創建面板類
    class ReceiveImagePanel extends JPanel {
        public void paint(Graphics g) {
            if (receiveImg != null) {
                g.clearRect(0, 0, this.getWidth(), this.getHeight());// 清除繪圖上下文的內容
                g.drawImage(receiveImg, 0, 0, this.getWidth(),
                        this.getHeight(), this);// 繪制指定大小的圖片
            }
        }
    }
}

服務器啟動

客戶端啟動

以上就是Java聊天室之使用Socket實現傳遞圖片的詳細內容,更多關於Java聊天室的資料請關註WalkonNet其它相關文章

推薦閱讀: