程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java小例子:通過Socket發送和接收文件

Java小例子:通過Socket發送和接收文件

編輯:關於JAVA

這是一個簡單的包含發送端和接收端的例子。發送端向接收端發送文件名和文件內容 ,接收端將收到的文件保存在磁盤上。接收端可以同時接收多個發送端傳來的文件,但沒 有處理文件同名的情況。

這個例子中設計了一個簡單的協議。發送的內容是這樣的:

文件名長度(4字節)—文件名—文件內容長度(4字節)—文件內容 。

接收端也按照這個結構進行解析。建議先看 Client 類,再看 Server 類。

01.import java.io.*;
02.import java.net.ServerSocket;
03.import java.net.Socket;
04.
05./**
06. * 簡單的文件發送與接收示例
07. */
08.public class FileTrasmission {
09.
10.    //程序入口
11.    public static void main(String[] args) throws Exception {
12.        int port = 7788;
13.        new Server(port, "c:\\save\\").start();
14.        new Client().sendFile("127.0.0.1", port, "c:\\迷失在康熙末年.txt");
15.    }
16.}
17.
18./**
19. * 接收端。可同時接收多個發送端發來的文件。但如果發來的文件是同名的話那就亂了。
20. */
21.class Server {
22.
23.    private int listenPort;
24.
25.    private String savePath;
26.
27.    /**
28.     * 構造方法
29.     *
30.     * @param listenPort 偵聽端口
31.     * @param savePath   接收的文件要保存的路徑
32.     *
33.     * @throws IOException 如果創建保存路徑失敗
34.     */
35.    Server(int listenPort, String savePath) throws IOException {
36.        this.listenPort = listenPort;
37.        this.savePath = savePath;
38.
39.        File file = new File(savePath);
40.        if (!file.exists() && !file.mkdirs()) {
41.            throw new IOException("無法創建文件夾 " + savePath);
42.        }
43.    }
44.
45.    // 開始偵聽
46.    public void start() {
47.        new ListenThread().start();
48.    }
49.
50.    // 網上抄來的,將字節轉成 int。b 長度不得小於 4,且只會取前 4 位。
51.    public static int b2i(byte[] b) {
52.        int value = 0;
53.        for (int i = 0; i < 4; i++) {
54.            int shift = (4 - 1 - i) * 8;
55.            value += (b[i] & 0x000000FF) << shift;
56.        }
57.        return value;
58.    }
59.
60.
61.    /**
62.     * 偵聽線程
63.     */
64.    private class ListenThread extends Thread {
65.
66.        @Override
67.        public void run() {
68.            try {
69.                ServerSocket server = new ServerSocket(listenPort);
70.
71.                // 開始循環
72.                while (true) {
73.                    Socket socket = server.accept();
74.                    new HandleThread(socket).start();
75.                }
76.            } catch (IOException e) {
77.                e.printStackTrace();
78.            }
79.        }
80.    }
81.
82.    /**
83.     * 讀取流並保存文件的線程
84.     */
85.    private class HandleThread extends Thread {
86.
87.        private Socket socket;
88.
89.        private HandleThread(Socket socket) {
90.            this.socket = socket;
91.        }
92.
93.        @Override
94.        public void run() {
95.            try {
96.                InputStream is = socket.getInputStream();
97.                readAndSave(is);
98.            } catch (IOException e) {
99.                e.printStackTrace();
100.            } finally {
101.                try {
102.                    socket.close();
103.                } catch (IOException e) {
104.                    // nothing to do
105.                }
106.            }
107.        }
108.
109.        // 從流中讀取內容並保存
110.        private void readAndSave(InputStream is) throws IOException {
111.            String filename = getFileName(is);
112.            int file_len = readInteger(is);
113.            System.out.println("接收文件:" + filename + ",長度:" + file_len);
114.
115.            readAndSave0(is, savePath + filename, file_len);
116.
117.            System.out.println("文件保存成功(" + file_len + "字節)。");
118.        }
119.
120.        private void readAndSave0(InputStream is, String path, int file_len) throws IOException {
121.            FileOutputStream os = getFileOS(path);
122.            readAndWrite(is, os, file_len);
123.            os.close();
124.        }
125.
126.        // 邊讀邊寫,直到讀取 size 個字節
127.        private void readAndWrite(InputStream is, FileOutputStream os, int size) throws IOException {
128.            byte[] buffer = new byte[4096];
129.            int count = 0;
130.            while (count < size) {
131.                int n = is.read(buffer);
132.                // 這裡沒有考慮 n = -1 的情況
133.                os.write(buffer, 0, n);
134.                count += n;
135.            }
136.        }
137.
138.        // 讀取文件名
139.        private String getFileName(InputStream is) throws IOException {
140.            int name_len = readInteger(is);
141.            byte[] result = new byte[name_len];
142.            is.read(result);
143.            return new String(result);
144.        }
145.
146.        // 讀取一個數字
147.        private int readInteger(InputStream is) throws IOException {
148.            byte[] bytes = new byte[4];
149.            is.read(bytes);
150.            return b2i(bytes);
151.        }
152.
153.        // 創建文件並返回輸出流
154.        private FileOutputStream getFileOS(String path) throws IOException {
155.            File file = new File(path);
156.            if (!file.exists()) {
157.                file.createNewFile();
158.            }
159.
160.            return new FileOutputStream(file);
161.        }
162.    }
163.}
164.
165./**
166. * 發送端
167. */
168.class Client {
169.
170.    // 網上抄來的,將 int 轉成字節
171.    public static byte[] i2b(int i) {
172.        return new byte[]{
173.                (byte) ((i >> 24) & 0xFF),
174.                (byte) ((i >> 16) & 0xFF),
175.                (byte) ((i >> 8) & 0xFF),
176.                (byte) (i & 0xFF)
177.        };
178.    }
179.
180.    /**
181.     * 發送文件。文件大小不能大於 {@link Integer#MAX_VALUE}
182.     *
183.     * @param hostname 接收端主機名或 IP 地址
184.     * @param port     接收端端口號
185.     * @param filepath 文件路徑
186.     *
187.     * @throws IOException 如果讀取文件或發送失敗
188.     */
189.    public void sendFile(String hostname, int port, String filepath) throws IOException {
190.        File file = new File(filepath);
191.        FileInputStream is = new FileInputStream(filepath);
192.
193.        Socket socket = new Socket(hostname, port);
194.        OutputStream os = socket.getOutputStream();
195.
196.        try {
197.            int length = (int) file.length();
198.            System.out.println("發送文件:" + file.getName() + ",長度:" + length);
199.
200.            // 發送文件名和文件內容
201.            writeFileName(file, os);
202.            writeFileContent(is, os, length);
203.        } finally {
204.            os.close();
205.            is.close();
206.        }
207.    }
208.
209.    // 輸出文件內容
210.    private void writeFileContent(InputStream is, OutputStream os, int length) throws IOException {
211.        // 輸出文件長度
212.        os.write(i2b(length));
213.
214.        // 輸出文件內容
215.        byte[] buffer = new byte[4096];
216.        int size;
217.        while ((size = is.read(buffer)) != -1) {
218.            os.write(buffer, 0, size);
219.        }
220.    }
221.
222.    // 輸出文件名
223.    private void writeFileName(File file, OutputStream os) throws IOException {
224.        byte[] fn_bytes = file.getName().getBytes();
225.
226.        os.write(i2b(fn_bytes.length));         // 輸出文件名長度
227.        os.write(fn_bytes);    // 輸出文件名
228.    }
229.}
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved