服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服务器之家 - 编程语言 - JAVA教程 - java基于Socket做一个简单下载器

java基于Socket做一个简单下载器

2020-06-07 12:20yesz12358 JAVA教程

这篇文章主要为大家详细介绍了java如何基于Socket制作一个简单下载器,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了java基于Socket制作下载器的过程,及相关代码,供大家参考,具体内容如下

1.首先要建立一个服务器用来处理信息并给客户端传输文件(电脑)
 我是用电脑开了一个WIFI,手机连上后使用scoket传输的 
SERVERIP要根据自己实际情况更改。端口也可以随便更改0~65535,尽量选大一点 

?
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
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
 
/**
 * 测试Android客户端与PC服务器通过socket进行交互 服务器端:接收客户端的信息并回送给客户
 *
 * @author Ameyume
 *
 */
public class Server implements Runnable {
 //定义传输的IP和端口信息
 public static final String SERVERIP = "192.168.155.1";
 //定义的9888端口
 public static final int SERVERPORT = 9888;
 //定义文件
 private File file = null;
 
 public static void main(String[] args) {
 //建立调用线程执行传输的方法
 Thread desktopServerThread = new Thread(new Server());
 desktopServerThread.start();
 }
 
 public void run() {
 try {
  System.out.println("S: Connecting...9888");
 
  //创建套接字
  ServerSocket serverSocket = new ServerSocket(SERVERPORT);
  while (true) {
  // 等待接受客户端请求
  Socket client = serverSocket.accept();
 
  System.out.println("S: Receiving...9888");
 
  try {
 
   // 接受客户端信息
   BufferedReader in = new BufferedReader(
    new InputStreamReader(client.getInputStream()));
   System.out.println("S: 接收客户端信息");
   // 读取客户端的信息
   String str = in.readLine();
   String str1 = str.substring(0,2);
   String str2 = str.substring(2);
   System.out.println(str);
   //根据客户端的请求找到对应的文件并把文件大小的值传过去
   if (str.equals("file_size")) {
   
   //定义你要传输的文件(我这里写的是E盘下的某个文件)
   file = new File("E:\\某个文件");
   //输入流
   FileInputStream fis = new FileInputStream(file);
   //输出流
   BufferedInputStream bis = new BufferedInputStream(fis);
   //计算将要传输的文件大小
   int sum = bis.available();
   //将int型的文件大小转成字符串
   String s = String.valueOf(sum);
   System.out.println(s);
   //建立输出流以发送文件大小的信息
   PrintWriter out = new PrintWriter(new BufferedWriter(
    new OutputStreamWriter(client.getOutputStream())),
    true);
   //发送文件的大小信息
   out.println(s);
   //关闭流
   out.flush();
   bis.close();
 
   } else if (str1.equals("ok")) {
   int a = Integer.parseInt(str2);
   
   // 客户端收到文件大小的值后,再根据客户端传来的“ok”将文件传过去
   BufferedOutputStream bos = new BufferedOutputStream(
    client.getOutputStream());
   
   System.out.println("S: 开始传输");
 
   //开始传输
   if (true) {
    //输入流
    FileInputStream fis = new FileInputStream(file);
    //跳过前面已经传输过的字节
    fis.skip(a);
    //缓冲输入流
    BufferedInputStream bis = new BufferedInputStream(
     fis);
 
    int t = -1;
    while ((t = bis.read()) >= 0) {
    bos.write(t);
    }
 
    String s = "已传输";
    //关闭流
    bos.flush();
    bis.close();
    bos.close();
    // serverSocket.close();
 
    System.out.println("S: Received: '" + s + "'");
   }
   } else {
   System.out
    .println("Not receiver anything from client!");
   }
  } catch (Exception e) {
   System.out.println("S: Error 1");
   e.printStackTrace();
  } finally {
   client.close();
   System.out.println("S: Done.");
  }
  }
 } catch (Exception e) {
  System.out.println("S: Error 2");
  e.printStackTrace();
 }
 }
 
}

 2.再建立一个客户端,我这里用的是安卓写的MainActivity.java(我是在手机上运行的) 

?
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
package com.xhy.zz;
 
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
 
 
public class MainActivity extends Activity {
 
 
 
 // 定义Handler
 public static Handler myHandler;
 
 // 定义intent
 private Intent intent;
 
 
 // 获取控件
 private TextView text_name;
 private TextView text_percent;
 private Button btn_start;
 private Button btn_stop;
 
 
 // 文件显示
 private TextView text_sel_file;
 
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 // TODO Auto-generated method stub
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 
 
 
 text_name = (TextView) findViewById(R.id.text_name);
 
 
 text_percent = (TextView) findViewById(R.id.text_percent);
 
 btn_start = (Button) findViewById(R.id.btn_start);
 
 btn_stop = (Button) findViewById(R.id.btn_stop);
 
 
 
 
 // 按钮一的返回信息,显示进度
 myHandler = new Handler() {
  @Override
  public void handleMessage(Message msg) {
  super.handleMessage(msg);
 
  if (msg.what == 0x0001) {
   Bundle data = msg.getData();
   String str = data.getString("value");
   text_percent.setText(str);
  }
  }
 };
 // 显式的方式调用HelloService
 intent = new Intent(this, DownService.class);
 // 设置启动按钮点击事件
 btn_start.setOnClickListener(new OnClickListener() {
  @Override
  public void onClick(View v) {
  
  // 开启服务
  startService(intent);
  
  }
 });
 // 设置停止按钮点击事件
 btn_stop.setOnClickListener(new OnClickListener() {
  @Override
  public void onClick(View v) {
  // 关闭服务
  stopService(intent);
  }
 });
 
 
 
 
 }
 
 /***
 * 被调用Activity一旦返回值 该回调方法将被系统自动调用
 */
 @Override
 protected void onActivityResult(int requestCode, int resultCode,
  Intent intent) {
 super.onActivityResult(requestCode, resultCode, intent);
 // 如果请求码是0
 // 并且返回的结果码为1
 // 请求的Activity可能返回多种结果码
 if (requestCode == 0 && resultCode == 1) {
  // 取出数据
  Bundle data = intent.getExtras();
  String str = data.getString("files");
  // 显示数据
  text_sel_file.setText(str);
 }
 }
 
}

3.activity_main.xml文件

?
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
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical" >
  
  
 
  <LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="20dp"
    android:orientation="horizontal" >
 
    <TextView
      android:id="@+id/text_name"
      android:layout_width="160dp"
      android:layout_height="wrap_content"
      android:layout_gravity="center_vertical"
      android:text="1" />
 
    <TextView
      android:id="@+id/text_percent"
      android:layout_width="50dp"
      android:layout_height="wrap_content"
      android:layout_gravity="center_vertical"
      android:layout_marginLeft="20dp"
      android:text="0%"/>
 
    <LinearLayout
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginLeft="20dp"
      android:orientation="vertical" >
      <Button
        android:id="@+id/btn_start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="start"
        />
      <Button
        android:id="@+id/btn_stop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="stop"
        />
      
    </LinearLayout>
  </LinearLayout
</LinearLayout>

4.DownService用于在后台开启线程执行下载 

?
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
package com.xhy.zz;
 
 
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
 
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
 
public class DownService extends Service {
 private static final String TAG = "Socket_Android";
 
 // Preferece机制操作的文件名
 public static final String PREFERENCE_NAME = "DownService";
 // Preferece机制的操作模式
 public static int MODE = Context.MODE_PRIVATE;
 
 // 线程
 private Thread workThread;
 // 定义文件名
 private String filename="file";
 
 // 端口号
 private int port = 9888;
 
 private boolean isStop = false;
 
 /***
 * 必须要实现的方法
 */
 @Override
 public IBinder onBind(Intent intent) {
 return null;
 }
 
 @Override
 public void onCreate() {
 super.onCreate();
 
 }
 
 @Override
 public int onStartCommand(Intent intent, int flags, int startId) {
 
 Log.v("TCP", filename);
 // 建立传输的方法
 Runnable backgroundWork = new Runnable() {
  @Override
  public void run() {
 
   // setTitle("测试Socket连接");
   Socket socket = null;
   Socket socket1 = null;
 
   try {
   /*
    * 指定Server的IP地址,此地址为局域网地址,如果是使用WIFI上网,则为PC机的WIFI IP地址
    * 在ipconfig查看到的IP地址如下: Ethernet adapter 无线网络连接:
    * Connection-specific DNS Suffix . : IP Address. . . .
    * . . . . . . . . : 192.168.155.1
    */
   InetAddress serverAddr = InetAddress
    .getByName("192.168.155.1");// TCPServer.SERVERIP
   Log.d("TCP", "C: Connecting...");
   Log.d("TCP", filename + " " + port);
   // 应用Server的IP和端口建立Socket对象,向服务端发送请求获取文件大小的值
   socket1 = new Socket(serverAddr, port);
   String message = "---Test_Socket_Android---";
 
   Log.d("TCP", "C: Sending: '" + message + "'");
 
   // 将信息通过这个对象来发送给Server
   PrintWriter out = new PrintWriter(new BufferedWriter(
    new OutputStreamWriter(
     socket1.getOutputStream())), true);
 
   // 把用户输入的内容发送给server
   out.println("file_size");
   out.flush();
 
   // 接收服务器信息
   BufferedReader in = new BufferedReader(
    new InputStreamReader(socket1.getInputStream()));
   // 获取文件大小
   String str1 = in.readLine();
 
   Log.d("TCP", str1);
   // 将文件大小转成int型
   int sum = Integer.parseInt(str1);
   Log.d("TCP", str1);
   // 关闭输入流
   in.close();
 
   SharedPreferences sharedPreferences = getSharedPreferences(
    PREFERENCE_NAME, MODE);
 
   SharedPreferences.Editor editor = sharedPreferences
    .edit();
   //取出已经传输了的字节
   int pre = sharedPreferences.getInt("DownService", 0);
   int _pre = pre;
   //将其转化为字符串以便发送给服务端
   String s = String.valueOf(_pre);
 
   // 应用Server的IP和端口建立Socket对象再次向服务端发送请求,以获取文件内容
   socket = new Socket(serverAddr, port);
 
   // 向服务端发送请求获得文件的字符
   PrintWriter out1 = new PrintWriter(
    new BufferedWriter(new OutputStreamWriter(
     socket.getOutputStream())), true);
 
   out1.println("ok"+s);
   out1.flush();
   out.close();
   
 
   // 定义输入流
   BufferedInputStream bis = new BufferedInputStream(
    socket.getInputStream());
 
   String file1 = filename;
   String file;
   // 判断手机是否插入了SDCard,是则将文件插入内存卡
   if (Environment.getExternalStorageState().equals(
    Environment.MEDIA_MOUNTED)) {
    File sdCard = Environment
     .getExternalStorageDirectory();
 
    // SD卡定义文件
    file = sdCard.getCanonicalFile() + "/" + file1;
    // 定义文件输出流
    FileOutputStream fos = new FileOutputStream(file,true);
    try {
    int t = -1;
    int downloaded = pre;
 
    // 定义每次传输的字节数
    byte[] buff = new byte[8192];
    Log.i("sum", sum + "");
    // 开始将服务端的文件写入手机SD卡中
    while ((t = bis.read(buff)) != -1) {
     if (isStop == true) {
     break;
     }
     fos.write(buff, 0, t);
     downloaded += t;
     
     //将传输的进度存储起来
     editor.putInt("DownService", downloaded);
     editor.commit();
     
     //当传完了则把存储信息归零
     if (downloaded == sum) {
     editor.putInt("DownService", 0);
     editor.commit();
     }
     // 获得文件传输的进度
     float wb = ((downloaded * 100) / (float) sum);
     int wi = (int) wb;
     System.out.println(downloaded);
     String str = String.valueOf(wi) + "%";
 
     // 将文件的传输进度给送给BaseActivity,以显示给用户
     Message msg = new Message(); // 生成消息
     // 生成消息
     msg.what = 0x0001; // 设置消息类型
     // 生成Bundle携带数据
     Bundle data = new Bundle();
     data.putString("value", str);
     msg.setData(data);
     // 利用Handler发送消息
     MainActivity.myHandler.sendMessage(msg);
 
    }
    
    // 关闭输入输出流
    bis.close();
    fos.flush();
    fos.close();
 
    } catch (Exception e) {
    bis.close();
    fos.flush();
    fos.close();
    }
   }
   Log.d(TAG, "From server:'已接收" + "'");
   } catch (UnknownHostException e) {
   Log.e(TAG, "192.168.155.1 is unkown server!");
   } catch (Exception e) {
   e.printStackTrace();
   } finally {
   try {
    socket.close();
   } catch (Exception e) {
    e.printStackTrace();
   }
   }
 
  }
  
 };
 workThread = new Thread(backgroundWork);
 // isAlive方法用于判断workThread线程是否被开启
 if (!workThread.isAlive()) {
  // 生成新线程
  workThread.start();
  Log.v("ServiceLife", "线程开始工作");
 } else {
  Log.v("workThread", "线程已经被调用");
 }
 
 return START_STICKY;
 }
 
 @Override
 public void onDestroy() {
 
 super.onDestroy();
 // 利用interrupt方式中断该线程
 isStop = true;
 
 Log.v("ServiceLife", "onDestroy方法被调用");
 }
 
}

5、最后别忘了注册AndroidManifest.xml

?
1
2
3
4
5
6
7
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" >
</uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" >
</uses-permission>
 
<service android:name=".DownService" ></service>

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

延伸 · 阅读

精彩推荐