java基于Socket做一個(gè)簡(jiǎn)單下載器
本文實(shí)例為大家分享了java基于Socket制作下載器的過(guò)程,及相關(guān)代碼,供大家參考,具體內(nèi)容如下
1.首先要建立一個(gè)服務(wù)器用來(lái)處理信息并給客戶端傳輸文件(電腦)
我是用電腦開(kāi)了一個(gè)WIFI,手機(jī)連上后使用scoket傳輸?shù)?nbsp;
SERVERIP要根據(jù)自己實(shí)際情況更改。端口也可以隨便更改0~65535,盡量選大一點(diǎn)
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;
/**
* 測(cè)試Android客戶端與PC服務(wù)器通過(guò)socket進(jìn)行交互 服務(wù)器端:接收客戶端的信息并回送給客戶
*
* @author Ameyume
*
*/
public class Server implements Runnable {
//定義傳輸?shù)腎P和端口信息
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) {
//建立調(diào)用線程執(zhí)行傳輸?shù)姆椒?
Thread desktopServerThread = new Thread(new Server());
desktopServerThread.start();
}
public void run() {
try {
System.out.println("S: Connecting...9888");
//創(chuàng)建套接字
ServerSocket serverSocket = new ServerSocket(SERVERPORT);
while (true) {
// 等待接受客戶端請(qǐng)求
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);
//根據(jù)客戶端的請(qǐng)求找到對(duì)應(yīng)的文件并把文件大小的值傳過(guò)去
if (str.equals("file_size")) {
//定義你要傳輸?shù)奈募ㄎ疫@里寫的是E盤下的某個(gè)文件)
file = new File("E:\\某個(gè)文件");
//輸入流
FileInputStream fis = new FileInputStream(file);
//輸出流
BufferedInputStream bis = new BufferedInputStream(fis);
//計(jì)算將要傳輸?shù)奈募笮?
int sum = bis.available();
//將int型的文件大小轉(zhuǎn)成字符串
String s = String.valueOf(sum);
System.out.println(s);
//建立輸出流以發(fā)送文件大小的信息
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(client.getOutputStream())),
true);
//發(fā)送文件的大小信息
out.println(s);
//關(guān)閉流
out.flush();
bis.close();
} else if (str1.equals("ok")) {
int a = Integer.parseInt(str2);
// 客戶端收到文件大小的值后,再根據(jù)客戶端傳來(lái)的“ok”將文件傳過(guò)去
BufferedOutputStream bos = new BufferedOutputStream(
client.getOutputStream());
System.out.println("S: 開(kāi)始傳輸");
//開(kāi)始傳輸
if (true) {
//輸入流
FileInputStream fis = new FileInputStream(file);
//跳過(guò)前面已經(jīng)傳輸過(guò)的字節(jié)
fis.skip(a);
//緩沖輸入流
BufferedInputStream bis = new BufferedInputStream(
fis);
int t = -1;
while ((t = bis.read()) >= 0) {
bos.write(t);
}
String s = "已傳輸";
//關(guān)閉流
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.再建立一個(gè)客戶端,我這里用的是安卓寫的MainActivity.java(我是在手機(jī)上運(yùn)行的)
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);
// 按鈕一的返回信息,顯示進(jìn)度
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);
}
}
};
// 顯式的方式調(diào)用HelloService
intent = new Intent(this, DownService.class);
// 設(shè)置啟動(dòng)按鈕點(diǎn)擊事件
btn_start.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 開(kāi)啟服務(wù)
startService(intent);
}
});
// 設(shè)置停止按鈕點(diǎn)擊事件
btn_stop.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 關(guān)閉服務(wù)
stopService(intent);
}
});
}
/***
* 被調(diào)用Activity一旦返回值 該回調(diào)方法將被系統(tǒng)自動(dòng)調(diào)用
*/
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
// 如果請(qǐng)求碼是0
// 并且返回的結(jié)果碼為1
// 請(qǐng)求的Activity可能返回多種結(jié)果碼
if (requestCode == 0 && resultCode == 1) {
// 取出數(shù)據(jù)
Bundle data = intent.getExtras();
String str = data.getString("files");
// 顯示數(shù)據(jù)
text_sel_file.setText(str);
}
}
}
3.activity_main.xml文件
<?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用于在后臺(tái)開(kāi)啟線程執(zhí)行下載
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機(jī)制操作的文件名
public static final String PREFERENCE_NAME = "DownService";
// Preferece機(jī)制的操作模式
public static int MODE = Context.MODE_PRIVATE;
// 線程
private Thread workThread;
// 定義文件名
private String filename="file";
// 端口號(hào)
private int port = 9888;
private boolean isStop = false;
/***
* 必須要實(shí)現(xiàn)的方法
*/
@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);
// 建立傳輸?shù)姆椒?
Runnable backgroundWork = new Runnable() {
@Override
public void run() {
// setTitle("測(cè)試Socket連接");
Socket socket = null;
Socket socket1 = null;
try {
/*
* 指定Server的IP地址,此地址為局域網(wǎng)地址,如果是使用WIFI上網(wǎng),則為PC機(jī)的WIFI IP地址
* 在ipconfig查看到的IP地址如下: Ethernet adapter 無(wú)線網(wǎng)絡(luò)連接:
* 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);
// 應(yīng)用Server的IP和端口建立Socket對(duì)象,向服務(wù)端發(fā)送請(qǐng)求獲取文件大小的值
socket1 = new Socket(serverAddr, port);
String message = "---Test_Socket_Android---";
Log.d("TCP", "C: Sending: '" + message + "'");
// 將信息通過(guò)這個(gè)對(duì)象來(lái)發(fā)送給Server
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(
socket1.getOutputStream())), true);
// 把用戶輸入的內(nèi)容發(fā)送給server
out.println("file_size");
out.flush();
// 接收服務(wù)器信息
BufferedReader in = new BufferedReader(
new InputStreamReader(socket1.getInputStream()));
// 獲取文件大小
String str1 = in.readLine();
Log.d("TCP", str1);
// 將文件大小轉(zhuǎn)成int型
int sum = Integer.parseInt(str1);
Log.d("TCP", str1);
// 關(guān)閉輸入流
in.close();
SharedPreferences sharedPreferences = getSharedPreferences(
PREFERENCE_NAME, MODE);
SharedPreferences.Editor editor = sharedPreferences
.edit();
//取出已經(jīng)傳輸了的字節(jié)
int pre = sharedPreferences.getInt("DownService", 0);
int _pre = pre;
//將其轉(zhuǎn)化為字符串以便發(fā)送給服務(wù)端
String s = String.valueOf(_pre);
// 應(yīng)用Server的IP和端口建立Socket對(duì)象再次向服務(wù)端發(fā)送請(qǐng)求,以獲取文件內(nèi)容
socket = new Socket(serverAddr, port);
// 向服務(wù)端發(fā)送請(qǐng)求獲得文件的字符
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;
// 判斷手機(jī)是否插入了SDCard,是則將文件插入內(nèi)存卡
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;
// 定義每次傳輸?shù)淖止?jié)數(shù)
byte[] buff = new byte[8192];
Log.i("sum", sum + "");
// 開(kāi)始將服務(wù)端的文件寫入手機(jī)SD卡中
while ((t = bis.read(buff)) != -1) {
if (isStop == true) {
break;
}
fos.write(buff, 0, t);
downloaded += t;
//將傳輸?shù)倪M(jìn)度存儲(chǔ)起來(lái)
editor.putInt("DownService", downloaded);
editor.commit();
//當(dāng)傳完了則把存儲(chǔ)信息歸零
if (downloaded == sum) {
editor.putInt("DownService", 0);
editor.commit();
}
// 獲得文件傳輸?shù)倪M(jìn)度
float wb = ((downloaded * 100) / (float) sum);
int wi = (int) wb;
System.out.println(downloaded);
String str = String.valueOf(wi) + "%";
// 將文件的傳輸進(jìn)度給送給BaseActivity,以顯示給用戶
Message msg = new Message(); // 生成消息
// 生成消息
msg.what = 0x0001; // 設(shè)置消息類型
// 生成Bundle攜帶數(shù)據(jù)
Bundle data = new Bundle();
data.putString("value", str);
msg.setData(data);
// 利用Handler發(fā)送消息
MainActivity.myHandler.sendMessage(msg);
}
// 關(guān)閉輸入輸出流
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線程是否被開(kāi)啟
if (!workThread.isAlive()) {
// 生成新線程
workThread.start();
Log.v("ServiceLife", "線程開(kāi)始工作");
} else {
Log.v("workThread", "線程已經(jīng)被調(diào)用");
}
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
// 利用interrupt方式中斷該線程
isStop = true;
Log.v("ServiceLife", "onDestroy方法被調(diào)用");
}
}
5、最后別忘了注冊(cè)AndroidManifest.xml
<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>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Java字符流與字節(jié)流區(qū)別與用法分析
- 詳解Java中字符流與字節(jié)流的區(qū)別
- Java編程中字節(jié)流與字符流IO操作示例
- 深入解析Java編程中面向字節(jié)流的一些應(yīng)用
- java使用Socket實(shí)現(xiàn)SMTP協(xié)議發(fā)送郵件
- java Socket實(shí)現(xiàn)網(wǎng)頁(yè)版在線聊天
- java實(shí)現(xiàn)一個(gè)簡(jiǎn)單TCPSocket聊天室功能分享
- Java基于Socket實(shí)現(xiàn)HTTP下載客戶端
- Java Socket編程實(shí)現(xiàn)簡(jiǎn)單的問(wèn)候服務(wù)
- Java socket字節(jié)流傳輸示例解析
相關(guān)文章
淺析Spring配置中的classpath:與classpath*:的區(qū)別
這篇文章主要介紹了Spring配置中的"classpath:"與"classpath*:"的區(qū)別,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08
Java調(diào)用Python腳本傳遞數(shù)據(jù)并返回計(jì)算結(jié)果
實(shí)際工程項(xiàng)目中可能會(huì)用到Java和python兩種語(yǔ)言結(jié)合進(jìn)行,這樣就會(huì)涉及到一個(gè)問(wèn)題,Java如何調(diào)用Python腳本,感興趣的可以了解一下2021-05-05
SpringBoot中整合Ehcache實(shí)現(xiàn)熱點(diǎn)數(shù)據(jù)緩存的詳細(xì)過(guò)程
這篇文章主要介紹了SpringBoot中整合Ehcache實(shí)現(xiàn)熱點(diǎn)數(shù)據(jù)緩存,SpringBoot 中使用 Ehcache 比較簡(jiǎn)單,只需要簡(jiǎn)單配置,說(shuō)白了還是 Spring Cache 的用法,合理使用緩存機(jī)制,可以很好地提高項(xiàng)目的響應(yīng)速度,需要的朋友可以參考下2023-04-04
Flyway詳解及Springboot集成Flyway的詳細(xì)教程
Flayway是一款數(shù)據(jù)庫(kù)版本控制管理工具,,支持?jǐn)?shù)據(jù)庫(kù)版本自動(dòng)升級(jí),Migrations可以寫成sql腳本,也可以寫在java代碼里。這篇文章主要介紹了Flyway詳解及Springboot集成Flyway的詳細(xì)教程的相關(guān)資料,需要的朋友可以參考下2020-07-07
Sa-Token記住我模式實(shí)現(xiàn)七天免登錄
這篇文章主要為大家介紹了Sa-Token記住我模式實(shí)現(xiàn)七天免登錄示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07

