您的位置:首页 > 移动开发 > Android开发

使用Socket做一个简单的下载器

2015-12-21 15:54 429 查看

1.首先要建立一个服务器用来处理信息并给客户端传输文件(电脑)

我是用电脑开了一个WIFI,手机连上后使用scoket传输的

SERVERIP要根据自己实际情况更改。端口也可以随便更改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服务器通过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(我是在手机上运行的)

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文件

<?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用于在后台开启线程执行下载

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

<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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  socket android server 下载