Socket多文件传输代码
本文是一个多线程多文件传输实例,客户端里修改ip和port即可实现,代码是完整的。
如果有不清楚的,可以给我留言。
服务端代码:
package com;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.ServerSocket;
import java.net.Socket;
public class FileServer implements Runnable {
private static final int DEFAULT_PORT = 7778;
private ServerSocket serverSocket;
public final static int PER_RECEIVE_SIZE = 1024 * 100;
/**
* 启动程序
*
* @param args
*/
public static void main(String[] args) {
FileServer server = new FileServer();
server.init();
Thread thread = new Thread(server);
thread.start();
}
public void init() {
try {
serverSocket = new ServerSocket(DEFAULT_PORT);
} catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
if (serverSocket == null) {
System.out.println("ERROR");
return;
}
while (true) {
DataInputStream serverIn = null;
DataOutputStream serverOut = null;
Socket socket = null;
try {
socket = serverSocket.accept();
serverIn = new DataInputStream(socket.getInputStream());
serverOut = new DataOutputStream(socket.getOutputStream());
while (true) {
try {
String command = readUTF(serverIn);
if (command == null || !command.contains("ClientInfo")) {
continue;
}
String fileName = new String(command.replaceAll("(.+<FileName>|<\\/FileName>\\S+)", "")
.toString().getBytes("UTF-8"), "UTF-8");
String fileSize = new String(command.replaceAll("(.+<FileLength>|<\\/FileLength>\\S+)", "")
.toString().getBytes("UTF-8"), "UTF-8");
String offset = new String(command.replaceAll(
"(.+<FilePointerStart>|<\\/FilePointerStart>\\S+)", "").toString().getBytes("UTF-8"),
"UTF-8");
String endset = new String(command.replaceAll("(.+<FilePointerEnd>|<\\/FilePointerEnd>\\S+)",
"").toString().getBytes("UTF-8"), "UTF-8");
File tempFile = new File("E:\\socket", fileName + ".temp");
File parentFile = tempFile.getParentFile();
boolean isCreate = initFile(tempFile, parentFile, Long.valueOf(fileSize));
if (!isCreate) {
closeSocket(serverIn, serverOut, socket);
}
String readyCommand = "ready=1";
writeUTF(serverOut, readyCommand);
String startCommand = readUTF(serverIn);
if ("sendStart".contains(startCommand)) {
RandomAccessFile randomAccessFile = new RandomAccessFile(tempFile, "rw");
long curPoint = Long.valueOf(offset);
long endPoint = Long.valueOf(endset);
byte[] buffer = null;
while (curPoint < endPoint && isContinue(serverIn)) {
if ((endPoint - curPoint + 1 < PER_RECEIVE_SIZE)) {
buffer = new byte[(int) (endPoint - curPoint + 1)];
} else {
buffer = new byte[(int) (PER_RECEIVE_SIZE)];
}
int amount;
long perLength = 0;
while ((amount = serverIn.read(buffer)) != -1) {
randomAccessFile.seek(curPoint);
randomAccessFile.write(buffer, 0, amount);
curPoint += amount;
perLength += amount;
if (perLength == buffer.length) {
break;
} else if (perLength > buffer.length) {
System.out.println("perLength" + perLength + "\tbuffer" + buffer.length);
System.out.println("传输出错");
}
}
System.out.println(" 指针位置 " + curPoint + " , 大小" + fileSize + "\t"
+ (curPoint == endPoint) + "\tendPoint:" + endPoint);
writeUTF(serverOut, "SerGotIt");
if (curPoint == endPoint + 1) {
writeUTF(serverOut, "receiveEnd");
closeRandomAccessFile(randomAccessFile);
break;
} else if (curPoint > endPoint) {
System.out.println("curPoint" + curPoint + "\tendPoint" + endPoint);
System.out.println("文件传输出错");
break;
}
}
}
String sendCommand = readUTF(serverIn);
if ("sendEnd".equals(sendCommand)) {
boolean isRename = renameFile(tempFile);
if (!isRename) {
System.out.println("文件重命名失败");
}
break;
}
} catch (Exception e) {
e.printStackTrace();
break;
}
}
} catch (Exception e) {
e.printStackTrace();
break;
} finally {
try {
closeSocket(serverIn, serverOut, socket);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public void closeRandomAccessFile(RandomAccessFile randomAccessFile) throws IOException {
randomAccessFile.close();
}
public void closeSocket(DataInputStream serverIn, DataOutputStream serverOut, Socket socket) throws IOException {
if (serverIn != null) {
serverIn.close();
}
if (serverOut != null) {
serverOut.close();
}
if (socket != null) {
socket.close();
}
}
public boolean renameFile(File tempFile) {
String filePath = tempFile.getPath();
filePath = filePath.substring(0, filePath.lastIndexOf(".temp"));
boolean isRename = tempFile.renameTo(new File(filePath));
System.out.println("重命名是否成功:" + isRename);
return isRename;
}
public String readUTF(DataInputStream dis) throws IOException {
return dis.readUTF();
}
public boolean isContinue(DataInputStream dis) {
boolean flag = false;
String command;
try {
command = dis.readUTF();
System.out.println(command);
if ("Continue".equals(command)) {
flag = true;
}
} catch (IOException e) {
e.printStackTrace();
flag = false;
}
return flag;
}
public boolean initFile(File tempFile, File parentFile, long fileSize) {
if (tempFile.exists()) {
return true;
}
if (parentFile.isDirectory()) {
creat(tempFile, fileSize);
return true;
} else {
boolean isCreate = parentFile.mkdirs();
if (isCreate) {
creat(tempFile, fileSize);
return true;
} else {
return false;
}
}
}
/**
* 创建文件
* @param targetFile 文件对象
* @param fileLength 文件字节长度
*/
public static void creat(File targetFile, long fileLength) {
long length = fileLength;//指定写入文件文件大小
byte[] buffer = new byte[PER_RECEIVE_SIZE];// 缓冲区1024 bytes
FileOutputStream fos;
try {
fos = new FileOutputStream(targetFile);
while (true) { // 建立缓冲区
if (length > PER_RECEIVE_SIZE) {
// 将缓冲区字节写入文件
try {
fos.write(buffer);// 写入缓冲
length = length - PER_RECEIVE_SIZE;
} catch (IOException e) {
e.printStackTrace();
}
} else {
byte[] buf = new byte[(int) length];
System.arraycopy(buffer, 0, buf, 0, (int) length);
try {
fos.write(buf);
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
}
public void writeUTF(DataOutputStream dos, String command) throws IOException {
dos.writeUTF(command);
dos.flush();
}
}
客户端代码
package com;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.Socket;
public class FileClient {
//服务端ip地址
private static final String DEFAULT_HOST = "192.10.33.95";
//服务端ip端口
private static final int DEFAULT_PORT = 7778;
public final static int PER_SEND_SIZE = 1024 * 100;
private Socket clientSocket;
/** 文件区域块 */
private int blockNum = 1;
/**
* 启动客户端程序
*
* @param args
*/
public static void main(String[] args) {
FileClient client = new FileClient();
client.init();
client.process();
}
public void init() {
try {
clientSocket = new Socket(DEFAULT_HOST, DEFAULT_PORT);
} catch (Exception e) {
e.printStackTrace();
}
}
public String[] getFileInfos(String fileName, long offset, long endset, long fileSize, long lastModifyTime) {
String[] fileInfos = new String[blockNum];
fileInfos[0] = "ClientInfo";
fileInfos[0] += "<FileName>" + fileName + "</FileName>";
fileInfos[0] += "<FilePointerStart>" + offset + "</FilePointerStart>";
fileInfos[0] += "<FilePointerEnd>" + endset + "</FilePointerEnd>";
fileInfos[0] += "<FileLength>" + fileSize + "</FileLength>";
fileInfos[0] += "<LastModifyTime>" + lastModifyTime + "</LastModifyTime>";
return fileInfos;
}
public void writeUTF(DataOutputStream dos, String command) throws IOException {
dos.writeUTF(command);
dos.flush();
}
public void writeBuffer(DataOutputStream dos, byte[] buffer) throws IOException {
dos.write(buffer);
dos.flush();
}
public String readUTF(DataInputStream dis) throws IOException {
return dis.readUTF();
}
public void process() {
if (clientSocket == null) {
System.out.println("ERROR");
return;
}
DataInputStream clientIn = null;
DataOutputStream clientOut = null;
try {
InputStream input = clientSocket.getInputStream();
OutputStream output = clientSocket.getOutputStream();
//发送文件
clientIn = new DataInputStream(new BufferedInputStream(input));
clientOut = new DataOutputStream(new BufferedOutputStream(output));
File tempFile = new File("D:\\tools\\QQMusicV7.72.1659.0907.exe");
String fileName = tempFile.getName();
long fileSize = tempFile.length();
long lastModifyTime = tempFile.lastModified();
long offset = 0; //区块起始位置
long endset = fileSize - 1; //区块结束位置
String[] fileInfos = getFileInfos(fileName, offset, endset, fileSize, lastModifyTime);
writeUTF(clientOut, fileInfos[0]);
while (true) {
String command = readUTF(clientIn);
if (!command.contains("ready=1")) {
continue;
}
writeUTF(clientOut, "sendStart");
RandomAccessFile randomAccessFile = new RandomAccessFile(tempFile, "r");
long curPoint = offset;
byte[] buffer = null;
while (curPoint < endset) {
writeUTF(clientOut, "Continue");
int length = 0;
try {
randomAccessFile.seek(curPoint);
if (endset - curPoint + 1 < PER_SEND_SIZE) {
buffer = new byte[(int) (endset - curPoint + 1)];
} else {
buffer = new byte[PER_SEND_SIZE];
}
length = randomAccessFile.read(buffer);
if (length == buffer.length) {
writeBuffer(clientOut, buffer);
for (;;) {
String serGotItCommand = readUTF(clientIn);
if ("SerGotIt".equals(serGotItCommand)) {
break;
}
}
curPoint += length;
System.out.println("curPoint:" + curPoint + "\tfileSize:" + fileSize);
if (curPoint == fileSize) {
System.out.println("发送完成");
break;
}
}
} catch (Exception e) {
e.printStackTrace();
break;
}
}
String endCommand = readUTF(clientIn);
System.out.println(endCommand);
if ("receiveEnd".equals(endCommand)) {
System.out.println("发送指令完成");
writeUTF(clientOut, "sendEnd");
break;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (clientIn != null) {
clientIn.close();
}
if (clientOut != null) {
clientOut.close();
}
if (clientSocket != null) {
clientSocket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}