Java Socket实现文件传输示例代码

https://blog.csdn.net/maguanghui_2012/article/details/54909044


这篇文章主要介绍了Java Socket实现文件传输示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

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

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

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

客户端代码:

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

服务端代码:

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

测试的结果(客户端):

测试的结果(服务端):

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值