Socket實現文件傳輸(二)
上次說了用Socket實現文件傳輸的前提工作,獲取手機的各種資源文件,這篇就主要講一下具體的實現過程,傳輸原理是基於Socket實現的。
實現文件傳輸
在拿到各種文件資源後(關於獲取手機資源文件請參照我的上一篇博客獲取手機文件資源),我們可以傳輸文件到電腦了,在傳輸文件之前先要連接設備,也就是在客戶端連接到一臺pc,Socket連接客戶端和服務端必須在線程裏面執行,
在點擊連接設備後,啓動新線程,執行Socket連接工作,在連接的時候有幾點需要注意的,
1. 客戶端和pc端必須在同一個局域網下;
2. 在連接時pc端需要關閉防火牆,不過我試過有時候不關也可以,但是最好還是關閉;
3. 在連接完成後Socket和流都要close掉,否則數據傳不過去;代碼如下:
package com.example.manager.Thread;
import android.util.Log;
import com.example.manager.Fragment.ConnectFragment;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.net.Socket;
/**
* Created by Dangelo on 2016/5/20.
*/
public class SocketThread implements Runnable {
private Socket socket;
private String IP;
private int port;
public SocketThread(Socket socket, String IP, int port){
this.socket = socket;
this.IP = IP;
this.port = port;
}
@Override
public void run() {
try {
socket = new Socket(IP, port);
ConnectFragment.connectHandler.sendEmptyMessage(0x000);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
writer.close();
socket.close();
} catch (Exception e) {
Log.e("Socket Error", e.toString());
ConnectFragment.connectHandler.sendEmptyMessage(0x111);
}
}
}
到這客戶端連接pc的工作基本上就完成了。接下來就是服務端的任務了。啓動服務端,在接收到客戶端的請求之後連接到客戶端,這下就能夠傳文件到pc了,在做這個項目的時候我在傳文件的基礎上還附加了一些傳輸命令功能,可以在客戶端直接控制pc執行一些操作,像常用的電源,音量,亮度,鼠標控制等等,這些操作方便了對pc的控制。
在傳輸文件和命令時需要區分它們的類別,我用的是Json數據來處理的,如果接收到的是command就執行命令操作,再根據後續的具體命令去執行具體的操作,如果是file就執行傳文件操作。這樣在處理數據的時候就很容易了,啓動後連接成功拿到當前傳過來的字符串,先判斷是傳輸文件還是傳輸命令,如果有“command”鍵就執行命令操作,並且拿到當前的命令類型,執行對應操作,代碼如下:
static ServerSocket ss = null;
public void run() {
try {
ss = new ServerSocket(30000);
System.out.println("服務端創建成功!");
while(true) {
Socket socket = ss.accept();
System.out.println("客戶端連接成功!");
System.out.println(socket.getLocalSocketAddress());
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
StringBuilder str = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
str.append(line);
}
if(str.toString().equals("")){
continue;
}
JSONObject jsonObject = new JSONObject(str.toString());
if(jsonObject.has("command")) { //傳輸命令
switch (jsonObject.get("command").toString()){
case "power" :
Runtime.getRuntime().exec(jsonObject.get("type").toString());
break;
case "volume" :
volumeOperation(jsonObject.get("type").toString());
break;
case "brightness" :
brightnessOperation(jsonObject.get("type").toString());
break;
case "mouse" :
mouseOperation(str.toString());
break;
case "driver" :
Socket driverSocket = ss.accept();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(driverSocket.getOutputStream()));
Storage storage = new Storage();
List<Map<String, String>> list = storage.getDriver();
StringBuilder buffer = new StringBuilder();
buffer.append("{'driver':[");
for (int i = 0; i < list.size(); i++) {
buffer.append("{")
.append("'name':'")
.append(list.get(i).get("name"))
.append("','totalSize':'")
.append(list.get(i).get("totalSize"))
.append("','availableSize':'")
.append(list.get(i).get("availableSize"));
if(i == list.size()-1){
buffer.append("'}]}");
} else {
buffer.append("'},");
}
}
writer.write(buffer.toString());
writer.close();
driverSocket.close();
break;
case "tools" :
Runtime.getRuntime().exec(jsonObject.get("type").toString());
break;
case "screenShot" :
Mouse mouse = new Mouse();
BufferedImage image = mouse.screenShot();
File file = new File("E:/QuickSend");
if(!file.exists()){
file.mkdirs();
}
mouse.saveScreenShot(image, "E:/QuickSend/ScreenShot-" + getTime() + ".png");
break;
}
} else { //傳輸文件
String fileName = jsonObject.get("fileName").toString();
// String filePath = jsonObject.get("savePath").toString();
File file = new File("E:/QuickSend");
if(!file.exists()){
file.mkdir(); //新建文件夾
}
/**
* 字節流讀取文件
*/
Socket fileSocket = ss.accept();
InputStream is = fileSocket.getInputStream();
FileOutputStream os = new FileOutputStream(file.getPath() + '/' + fileName);
byte[] c = new byte[1024 * 10];
int b;
while ((b = is.read(c)) > 0) {
os.write(c, 0, b);
}
is.close();
os.close();
fileSocket.close();
}
reader.close();
socket.close();
}
} catch (Exception e) {
System.out.println(e.toString());
}
}
所有的操作類型都是通過Json數據發送過來的,這樣很容易處理,通過鍵,拿到值,執行操作,服務端界面如圖
服務端開啓後會顯示出當前連接網絡的ip地址,在客戶端輸入這個ip地址就能連接成功了,附上功能函數的代碼:
傳輸文件:
String fileName = jsonObject.get("fileName").toString();
File file = new File("E:/QuickSend");
if(!file.exists()){
file.mkdir(); //新建文件夾
}
/**
* 字節流讀取文件
*/
Socket fileSocket = ss.accept();
InputStream is = fileSocket.getInputStream();
FileOutputStream os = new FileOutputStream(file.getPath() + '/' + fileName);
byte[] c = new byte[1024 * 10];
int b;
while ((b = is.read(c)) > 0) {
os.write(c, 0, b);
}
is.close();
os.close();
fileSocket.close();
獲取電腦盤符:
public class Storage {
private List< Map<String, String> > list;
/**
* 獲取硬盤的每個盤符
*/
public List< Map<String, String> > getDriver(){
// 當前文件系統類
FileSystemView fsv = FileSystemView.getFileSystemView();
// 列出所有windows 磁盤
File [] files = File.listRoots();
System.out.println(files.length);
list = new ArrayList<>();
// 顯示磁盤卷標
for (File file : files) {
if(!fsv.getSystemDisplayName(file).equals("")){
Map<String, String> map = new HashMap<>();
map.put("name", fsv.getSystemDisplayName(file));
map.put("totalSize", FormatFileSize(file.getTotalSpace()));
map.put("availableSize", FormatFileSize(file.getFreeSpace()));
list.add(map);
System.out.print(fsv.getSystemDisplayName(file));
System.out.print("總大小" + FormatFileSize(file.getTotalSpace()) + " ");
System.out.println("剩餘" + FormatFileSize(file.getFreeSpace()));
}
}
return list;
}
private String FormatFileSize(long fileS) {
DecimalFormat df = new DecimalFormat("#.00");
String fileSizeString ;
if (fileS < 1024) {
fileSizeString = df.format((double) fileS) + "B";
} else if (fileS < 1048576) {
fileSizeString = df.format((double) fileS / 1024) + "KB";
} else if (fileS < 1073741824) {
fileSizeString = df.format((double) fileS / 1048576) + "MB";
} else {
fileSizeString = df.format((double) fileS / 1073741824) + "GB";
}
return fileSizeString;
}
}
case "driver" :
Socket driverSocket = ss.accept();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(driverSocket.getOutputStream()));
Storage storage = new Storage();
List<Map<String, String>> list = storage.getDriver();
StringBuilder buffer = new StringBuilder();
buffer.append("{'driver':[");
for (int i = 0; i < list.size(); i++) {
buffer.append("{")
.append("'name':'")
.append(list.get(i).get("name"))
.append("','totalSize':'")
.append(list.get(i).get("totalSize"))
.append("','availableSize':'")
.append(list.get(i).get("availableSize"));
if(i == list.size()-1){
buffer.append("'}]}");
} else {
buffer.append("'},");
}
}
writer.write(buffer.toString());
writer.close();
driverSocket.close();
break;
鼠標操作:
public class Mouse {
private Dimension dimension;
private Robot robot;
private Point point;
private final static String DIRECTION_UP = "up";
private final static String DIRECTION_DOWN = "down";
public Mouse() {
dimension = Toolkit.getDefaultToolkit().getScreenSize(); //獲取屏幕尺寸
try {
robot = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
}
/**
* 移動鼠標位置
*/
public void move(int x,int y){
point = MouseInfo.getPointerInfo().getLocation();
point.x += -x;
point.y += -y;
robot.mouseMove(point.x,point.y); //移動鼠標到x,y位置
}
/**
* 單擊
*/
public void singleClick(){
point = MouseInfo.getPointerInfo().getLocation();
robot.mouseMove(point.x, point.y);
robot.mousePress(InputEvent.BUTTON1_MASK); //按下鼠標上按鍵
robot.mouseRelease(InputEvent.BUTTON1_MASK); //釋放鼠標上按鍵
}
/**
* 雙擊
*/
public void doubleClick(){
point = MouseInfo.getPointerInfo().getLocation();
robot.mouseMove(point.x, point.y);
robot.mousePress(InputEvent.BUTTON1_MASK); //按下鼠標左按鍵
robot.mouseRelease(InputEvent.BUTTON1_MASK); //釋放鼠標左按鍵
robot.delay(100);
robot.mousePress(InputEvent.BUTTON1_MASK); //再次按下鼠標左按鍵
robot.mouseRelease(InputEvent.BUTTON1_MASK); //釋放鼠標左按鍵
}
/**
* 右擊
*/
public void rightClick(){
point = MouseInfo.getPointerInfo().getLocation();
robot.mouseMove(point.x, point.y);
robot.mousePress(InputEvent.BUTTON3_MASK);
robot.mouseRelease(InputEvent.BUTTON3_MASK);
}
/**
* 鼠標滾輪的滑動
*/
public void wheel(String direction){
if(direction.equals(DIRECTION_UP)) {
robot.mouseWheel(-1); //滾輪上滑
} else if(direction.equals(DIRECTION_DOWN)){
robot.mouseWheel(1); //滾輪下滑
}
}
public void direction(String key){
switch (key){
case "up" :
robot.keyPress(KeyEvent.VK_UP);
break;
case "down" :
robot.keyPress(KeyEvent.VK_DOWN);
break;
case "left" :
robot.keyPress(KeyEvent.VK_LEFT);
break;
case "right" :
robot.keyPress(KeyEvent.VK_RIGHT);
break;
case "home" :
robot.keyPress(KeyEvent.VK_HOME);
break;
case "end" :
robot.keyPress(KeyEvent.VK_END);
break;
}
}
/**
* 獲取屏幕截圖
*/
public BufferedImage screenShot(){
return robot.createScreenCapture(new Rectangle(0,0,dimension.width, dimension.height));
}
/**
* 保存屏幕截圖
*/
public void saveScreenShot(BufferedImage image, String path){
try {
ImageIO.write(image, "png", new File(path));
} catch (IOException e) {
System.out.println(e.toString());
}
}
}
語音識別:這塊主要是用的訊飛語音的接口,http://www.xfyun.cn/
獲取當前路連接網絡的IP地址:
package Utils;
/**
* Created byDangelo on 2016/7/22.
*/
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
public class NetWorkIP {
publicString getIP(){
Enumeration allNetInterfaces = null;
try {
allNetInterfaces = NetworkInterface.getNetworkInterfaces();
}catch (java.net.SocketException e) {
e.printStackTrace();
}
InetAddress ip = null;
while(allNetInterfaces.hasMoreElements())
{
NetworkInterface netInterface = (NetworkInterface) allNetInterfaces
.nextElement();
System.out.println(netInterface.getName());
Enumeration addresses = netInterface.getInetAddresses();
while (addresses.hasMoreElements())
{
ip = (InetAddress) addresses.nextElement();
if (ip != null && ip instanceofInet4Address)
{
System.out.println("/u672c/u673a/u7684IP = "
+ip.getHostAddress());
if(ip.getHostAddress().equals("127.0.0.1")){
continue;
}
return ip.getHostAddress();
}
}
}
return"暫無網絡連接";
}
}
其它的操作都是一些簡單的命令執行,直接Runtime.getRuntime().exec(“xxxx”);方法中傳cmd命令就行了,
下面附上一些常用命令:
“Shutdown -s” 關機
“Shutdown -h” 睡眠
“Shutdown -r” 重啓
“explorer” 資源管理器
“cmd –c start teskmgr” 任務管理器
"cmd /c start" 命令提示符
“cmd /c start control” 控制面板
“”notepad 記事本
“calc” 計算器
“dvdplay Windows” Windows MediaPlay
“write” 寫字板
“mspaint” 畫圖板
“cmd /c start start www.baidu.com”訪問百度
“cmd /c start start www.baidu.com/s?wd=xxxxx" 搜索xxxxx
到這裏,Socket實現文件傳輸就全部介紹完了,Manager應用的功能也就介紹完了。通過這個項目,我對Socket的理解更加深入,了,這對以後的學習也會有很大幫助,希望這些內容能對大家有所幫助。
項目客戶端地址:https://github.com/xiyouZmt/Remote-Manage
項目服務端地址:https://github.com/xiyouZmt/Remote-Manage-Server