package hillfly.wifichat.common.socket.tcp;
import hillfly.wifichat.common.BaseApplication;
import hillfly.wifichat.consts.Constant;
import hillfly.wifichat.model.FileState;
import hillfly.wifichat.model.Message;
import hillfly.wifichat.model.Message.CONTENT_TYPE;
import hillfly.wifichat.util.Logger;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import android.content.Context;
import android.os.Handler;
public class TcpService implements Runnable {
private static final Logger logger = Logger.getLogger(TcpService.class);
private ServerSocket serviceSocket;
private boolean SCAN_FLAG = false; // 接收扫描标识
private Thread mThread;
ArrayList<FileState> receivedFileNames;
ArrayList<SaveFileToDisk> saveFileToDisks;
private static Handler mHandler;
private String filePath = null; // 存放接收文件的路径
private static TcpService instance; // 唯一实例
private boolean IS_THREAD_STOP = false; // 是否线程开始标志
private TcpService() {
try {
serviceSocket = new ServerSocket(Constant.TCP_SERVER_RECEIVE_PORT);
saveFileToDisks = new ArrayList<TcpService.SaveFileToDisk>();
logger.d("建立监听服务器ServerSocket成功");
}
catch (IOException e) {
// TODO Auto-generated catch block
logger.d("建立监听服务器ServerSocket失败");
e.printStackTrace();
}
mThread = new Thread(this);
}
/**
* <p>
* 获取TcpService实例
* <p>
* 单例模式,返回唯一实例
*/
public static TcpService getInstance(Context context) {
if (instance == null) {
instance = new TcpService();
}
return instance;
}
public static void setHandler(Handler paramHandler) {
mHandler = paramHandler;
}
public void setSavePath(String fileSavePath) {
logger.d("设置存储路径成功,路径为" + fileSavePath);
this.filePath = fileSavePath;
// REV_FLAG=true;
}
public TcpService(Context context) {
this();
}
private void scan_recv() {
try {
Socket socket = serviceSocket.accept(); // 接收UDP数据报
// socket.setSoTimeout(5000); // 设置掉线时间
logger.d("客户端连接成功");
SaveFileToDisk fileToDisk = new SaveFileToDisk(socket, filePath);
fileToDisk.start();
}
catch (IOException e) {
e.printStackTrace();
logger.d("客户端连接失败");
SCAN_FLAG = false;
}
}
@Override
public void run() {
// TODO Auto-generated method stub
logger.d("TCP_Service线程开启");
while (!IS_THREAD_STOP) {
if (SCAN_FLAG) {
scan_recv();
}
}
}
public void release() {
if (null != serviceSocket && !serviceSocket.isClosed())
try {
serviceSocket.close();
serviceSocket = null;
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (SCAN_FLAG == true)
;// 直到SCAN_FLAG为false的时候退出循环
SCAN_FLAG = false;
IS_THREAD_STOP = true;
}
public void startReceive() {
SCAN_FLAG = true; // 使能扫描接收标识
if (!mThread.isAlive())
mThread.start(); // 开启线程
}
public void startReceive(ArrayList<FileState> receivedFileNames) {
SCAN_FLAG = true; // 使能扫描接收标识
if (!mThread.isAlive())
mThread.start(); // 开启线程
this.receivedFileNames = receivedFileNames;
}
public void stopReceive() {
while (SCAN_FLAG == true)
;
SCAN_FLAG = false; // 失能扫描接收标识
}
public class SaveFileToDisk extends Thread {
private boolean SCAN_RECIEVE = true;
private InputStream input = null;
private DataInputStream dataInput;
private byte[] mBuffer = new byte[Constant.READ_BUFFER_SIZE];// 声明接收数组
private String savePath;
private String type[] = { "TEXT", "IMAGE", "FILE", "VOICE" };
public SaveFileToDisk(Socket socket) {
try {
input = socket.getInputStream();
dataInput = new DataInputStream(input);
logger.d("获取网络输入流成功");
}
catch (IOException e) {
// TODO Auto-generated catch block
logger.d("获取网络输入流失败");
SCAN_RECIEVE = false;
e.printStackTrace();
}
}
public SaveFileToDisk(Socket socket, String savePath) {
this(socket);
this.savePath = savePath;
}
public void recieveFile() {
int readSize = 0;
FileOutputStream fileOutputStream = null;
BufferedOutputStream bufferOutput = null;
String strFiledata;
String[] strData = null;
String fileSavePath;
try {
strFiledata = dataInput.readUTF().toString();
strData = strFiledata.split("!");
long length = Long.parseLong(strData[1]);// 文件大小
logger.d("传输文件类型:" + strData[3]);
fileSavePath = savePath + File.separator + strData[2] + File.separator + strData[0];
fileOutputStream = new FileOutputStream(new File(fileSavePath));// 创建文件流
logger.d("文件存储路径:" + fileSavePath);
FileState fileState = new FileState(length, 0, fileSavePath, getType(strData[3]));
BaseApplication.recieveFileStates.put(fileSavePath, fileState);
FileState fs = BaseApplication.recieveFileStates.get(fileSavePath);
bufferOutput = new BufferedOutputStream(fileOutputStream);// 创建带缓冲区的文件流
long currentLength = 0;
int count = 0;
while (-1 != (readSize = dataInput.read(mBuffer))) {
bufferOutput.write(mBuffer, 0, readSize);
currentLength += readSize;
count++;
if (count % 10 == 0) {
//long Length = currentLength - lastLength;
fs.currentSize = currentLength;
fs.percent = (int) ((float) currentLength / (float) length * 100);
switch (fs.type) {
case IMAGE:
break;
case VOICE:
break;
case FILE:
android.os.Message msg = mHandler.obtainMessage();
msg.obj = fs;
msg.sendToTarget();
break;
default:
break;
}
}
}
// 将byte数组的数据写进指定路径
bufferOutput.flush();
input.close();
dataInput.close();
bufferOutput.close();
fileOutputStream.close();
switch (fs.type) {
case IMAGE:
break;
case VOICE:
break;
case FILE:
android.os.Message msg = mHandler.obtainMessage();
fs.percent = 100;
msg.obj = fs;
msg.sendToTarget();
break;
default:
break;
}
BaseApplication.recieveFileStates.remove(fs.fileName);
}
catch (IOException e) {
// TODO Auto-generated catch block
logger.d("写入文件失败");
e.printStackTrace();
}
}
private Message.CONTENT_TYPE getType(String string) {
if (string.equals(type[0]))
return CONTENT_TYPE.TEXT;
else if (string.equals(type[1]))
return CONTENT_TYPE.IMAGE;
else if (string.equals(type[2]))
return CONTENT_TYPE.FILE;
else if (string.equals(type[3]))
return CONTENT_TYPE.VOICE;
return null;
}
@Override
public void run() {
super.run();
logger.d("SaveFileToDisk线程开启");
if (SCAN_RECIEVE)
recieveFile();
}
}
}