Java Socket实现文件传输

最近学Socket学上瘾了,就写了一个简单的文件传输程序。

客户端设计思路:客户端与服务端建立连接,选择客户端本地文件,先将文件名及大小等属性发送给服务端,再将文件通过流的方式传输给服务端。传输的进度打印到控制台中,直到传输完成。

服务端设计思路:服务端接收客户端的请求(阻塞式),每接收到一个客户端请求连接后,就新开一个处理文件的线程,开始写入流,将文件到服务器的指定目录下,并与传输过来的文件同名。
下面是客户端和服务端的代码实现:

客户端代码:

1. import
2. import
3. import
4. import
5.   
6. /**
7.  * 文件传输Client端<br>
8.  * 功能说明:
9.  *
10.  * @author 大智若愚的小懂
11.  * @Date 2016年09月01日
12.  * @version 1.0
13.  */
14. public class FileTransferClient extends
15.   
16. private static final String SERVER_IP = "127.0.0.1"; // 服务端IP
17. private static final int SERVER_PORT = 8899; // 服务端端口
18.   
19. private
20.   
21. private
22.   
23. private
24.   
25. /**
26.      * 构造函数<br/>
27.      * 与服务器建立连接
28.      * @throws Exception
29.      */
30. public FileTransferClient() throws
31. super(SERVER_IP, SERVER_PORT);  
32. this.client = this;  
33. "Cliect[port:" + client.getLocalPort() + "] 成功连接服务端");  
34.     }  
35.   
36. /**
37.      * 向服务端传输文件
38.      * @throws Exception
39.      */
40. public void sendFile() throws
41. try
42. new File("E:\\JDK1.6中文参考手册(JDK_API_1_6_zh_CN).CHM");  
43. if(file.exists()) {  
44. new
45. new
46.   
47. // 文件名和长度
48.                 dos.writeUTF(file.getName());  
49.                 dos.flush();  
50.                 dos.writeLong(file.length());  
51.                 dos.flush();  
52.   
53. // 开始传输文件
54. "======== 开始传输文件 ========");  
55. byte[] bytes = new byte[1024];  
56. int length = 0;  
57. long progress = 0;  
58. while((length = fis.read(bytes, 0, bytes.length)) != -1) {  
59. 0, length);  
60.                     dos.flush();  
61.                     progress += length;  
62. "| " + (100*progress/file.length()) + "% |");  
63.                 }  
64.                 System.out.println();  
65. "======== 文件传输成功 ========");  
66.             }  
67. catch
68.             e.printStackTrace();  
69. finally
70. if(fis != null)  
71.                 fis.close();  
72. if(dos != null)  
73.                 dos.close();  
74.             client.close();  
75.         }  
76.     }  
77.   
78. /**
79.      * 入口
80.      * @param args
81.      */
82. public static void
83. try
84. new FileTransferClient(); // 启动客户端连接
85. // 传输文件
86. catch
87.             e.printStackTrace();  
88.         }  
89.     }  
90.   
91. }



服务端代码:

1. import
2. import
3. import
4. import
5. import
6. import
7. import
8.   
9. /**
10.  * 文件传输Server端<br>
11.  * 功能说明:
12.  *
13.  * @author 大智若愚的小懂
14.  * @Date 2016年09月01日
15.  * @version 1.0
16.  */
17. public class FileTransferServer extends
18.   
19. private static final int SERVER_PORT = 8899; // 服务端端口
20.   
21. private static DecimalFormat df = null;  
22.   
23. static
24. // 设置数字格式,保留一位有效小数
25. new DecimalFormat("#0.0");  
26.         df.setRoundingMode(RoundingMode.HALF_UP);  
27. 1);  
28. 1);  
29.     }  
30.   
31. public FileTransferServer() throws
32. super(SERVER_PORT);  
33.     }  
34.   
35. /**
36.      * 使用线程处理每个客户端传输的文件
37.      * @throws Exception
38.      */
39. public void load() throws
40. while (true) {  
41. // server尝试接收其他Socket的连接请求,server的accept方法是阻塞式的
42. this.accept();  
43. /**
44.              * 我们的服务端处理客户端的连接请求是同步进行的, 每次接收到来自客户端的连接请求后,
45.              * 都要先跟当前的客户端通信完之后才能再处理下一个连接请求。 这在并发比较多的情况下会严重影响程序的性能,
46.              * 为此,我们可以把它改为如下这种异步处理与客户端通信的方式
47.              */
48. // 每接收到一个Socket就建立一个新的线程来处理它
49. new Thread(new
50.         }  
51.     }  
52.   
53. /**
54.      * 处理客户端传输过来的文件线程类
55.      */
56. class Task implements
57.   
58. private
59.   
60. private
61.   
62. private
63.   
64. public
65. this.socket = socket;  
66.         }  
67.   
68. @Override
69. public void
70. try
71. new
72.   
73. // 文件名和长度
74.                 String fileName = dis.readUTF();  
75. long
76. new File("D:\\FTCache");  
77. if(!directory.exists()) {  
78.                     directory.mkdir();  
79.                 }  
80. new
81. new
82.   
83. // 开始接收文件
84. byte[] bytes = new byte[1024];  
85. int length = 0;  
86. while((length = dis.read(bytes, 0, bytes.length)) != -1) {  
87. 0, length);  
88.                     fos.flush();  
89.                 }  
90. "======== 文件接收成功 [File Name:" + fileName + "] [Size:" + getFormatFileSize(fileLength) + "] ========");  
91. catch
92.                 e.printStackTrace();  
93. finally
94. try
95. if(fos != null)  
96.                         fos.close();  
97. if(dis != null)  
98.                         dis.close();  
99.                     socket.close();  
100. catch
101.             }  
102.         }  
103.     }  
104.   
105. /**
106.      * 格式化文件大小
107.      * @param length
108.      * @return
109.      */
110. private String getFormatFileSize(long
111. double size = ((double) length) / (1 << 30);  
112. if(size >= 1) {  
113. return df.format(size) + "GB";  
114.         }  
115. double) length) / (1 << 20);  
116. if(size >= 1) {  
117. return df.format(size) + "MB";  
118.         }  
119. double) length) / (1 << 10);  
120. if(size >= 1) {  
121. return df.format(size) + "KB";  
122.         }  
123. return length + "B";  
124.     }  
125.   
126. /**
127.      * 入口
128.      * @param args
129.      */
130. public static void
131. try
132. new FileTransferServer(); // 启动服务端
133.             server.load();  
134. catch
135.             e.printStackTrace();  
136.         }  
137.     }  
138. }



测试的结果(客户端):

java socket传输文件中文乱码DataOutputStream java socket传输大文件_服务端

测试的结果(服务端):

java socket传输文件中文乱码DataOutputStream java socket传输大文件_服务端_02