java基于Socket做一個簡單下載器
本文實例為大家分享了java基于Socket制作下載器的過程,及相關(guān)代碼,供大家參考,具體內(nèi)容如下
1.首先要建立一個服務(wù)器用來處理信息并給客戶端傳輸文件(電腦)
我是用電腦開了一個WIFI,手機連上后使用scoket傳輸?shù)?nbsp;
SERVERIP要根據(jù)自己實際情況更改。端口也可以隨便更改0~65535,盡量選大一點
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服務(wù)器通過socket進行交互 服務(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) { // 等待接受客戶端請求 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ù)客戶端的請求找到對應(yīng)的文件并把文件大小的值傳過去 if (str.equals("file_size")) { //定義你要傳輸?shù)奈募ㄎ疫@里寫的是E盤下的某個文件) file = new File("E:\\某個文件"); //輸入流 FileInputStream fis = new FileInputStream(file); //輸出流 BufferedInputStream bis = new BufferedInputStream(fis); //計算將要傳輸?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ù)客戶端傳來的“ok”將文件傳過去 BufferedOutputStream bos = new BufferedOutputStream( client.getOutputStream()); System.out.println("S: 開始傳輸"); //開始傳輸 if (true) { //輸入流 FileInputStream fis = new FileInputStream(file); //跳過前面已經(jīng)傳輸過的字節(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.再建立一個客戶端,我這里用的是安卓寫的MainActivity.java(我是在手機上運行的)
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); } } }; // 顯式的方式調(diào)用HelloService intent = new Intent(this, DownService.class); // 設(shè)置啟動按鈕點擊事件 btn_start.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 開啟服務(wù) startService(intent); } }); // 設(shè)置停止按鈕點擊事件 btn_stop.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 關(guān)閉服務(wù) stopService(intent); } }); } /*** * 被調(diào)用Activity一旦返回值 該回調(diào)方法將被系統(tǒng)自動調(diào)用 */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); // 如果請求碼是0 // 并且返回的結(jié)果碼為1 // 請求的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用于在后臺開啟線程執(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機制操作的文件名 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; /*** * 必須要實現(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("測試Socket連接"); Socket socket = null; Socket socket1 = null; try { /* * 指定Server的IP地址,此地址為局域網(wǎng)地址,如果是使用WIFI上網(wǎng),則為PC機的WIFI IP地址 * 在ipconfig查看到的IP地址如下: Ethernet adapter 無線網(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對象,向服務(wù)端發(fā)送請求獲取文件大小的值 socket1 = new Socket(serverAddr, port); String message = "---Test_Socket_Android---"; Log.d("TCP", "C: Sending: '" + message + "'"); // 將信息通過這個對象來發(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對象再次向服務(wù)端發(fā)送請求,以獲取文件內(nèi)容 socket = new Socket(serverAddr, port); // 向服務(wù)端發(fā)送請求獲得文件的字符 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,是則將文件插入內(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 + ""); // 開始將服務(wù)端的文件寫入手機SD卡中 while ((t = bis.read(buff)) != -1) { if (isStop == true) { break; } fos.write(buff, 0, t); downloaded += t; //將傳輸?shù)倪M度存儲起來 editor.putInt("DownService", downloaded); editor.commit(); //當(dāng)傳完了則把存儲信息歸零 if (downloaded == sum) { editor.putInt("DownService", 0); editor.commit(); } // 獲得文件傳輸?shù)倪M度 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; // 設(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線程是否被開啟 if (!workThread.isAlive()) { // 生成新線程 workThread.start(); Log.v("ServiceLife", "線程開始工作"); } 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、最后別忘了注冊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>
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
淺析Spring配置中的classpath:與classpath*:的區(qū)別
這篇文章主要介紹了Spring配置中的"classpath:"與"classpath*:"的區(qū)別,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-08-08Java調(diào)用Python腳本傳遞數(shù)據(jù)并返回計算結(jié)果
實際工程項目中可能會用到Java和python兩種語言結(jié)合進行,這樣就會涉及到一個問題,Java如何調(diào)用Python腳本,感興趣的可以了解一下2021-05-05SpringBoot中整合Ehcache實現(xiàn)熱點數(shù)據(jù)緩存的詳細過程
這篇文章主要介紹了SpringBoot中整合Ehcache實現(xiàn)熱點數(shù)據(jù)緩存,SpringBoot 中使用 Ehcache 比較簡單,只需要簡單配置,說白了還是 Spring Cache 的用法,合理使用緩存機制,可以很好地提高項目的響應(yīng)速度,需要的朋友可以參考下2023-04-04Flyway詳解及Springboot集成Flyway的詳細教程
Flayway是一款數(shù)據(jù)庫版本控制管理工具,,支持數(shù)據(jù)庫版本自動升級,Migrations可以寫成sql腳本,也可以寫在java代碼里。這篇文章主要介紹了Flyway詳解及Springboot集成Flyway的詳細教程的相關(guān)資料,需要的朋友可以參考下2020-07-07