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. }
测试的结果(客户端):
测试的结果(服务端):