使用说明:请将TransferClient, TransferServer, TempFile三个类编译,他们的类包是FileServer.
客户端:
修改TransferClient: serPort, serIP, filePath, blockNum,的值来符合您机器的系统环境;或者用命令行
格式: java FileServer.TransferClient 文件路径+文件名 服务器IP地址 端口 线程数
C:\>java FileServer.TransferClient e:\GREbulletin.pdf 192.168.1.105 2008 5
服务端:
修改TransferServer: serPort, tempFolder的值来符合您机器的系统环境;或者用命令行
格式: java FileServer.TransferServer 端口 文件夹路径
C:\>java FileServer.TransferServer 2008 F:\tempFolder
文件传输服务端---------------------------------------------------------
package FileServer; 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.ServerSocket; import java.net.Socket; import java.net.SocketException; /** * Description Socket文件传输服务端 * 默认支持多线程传输,未支持断点续传,未支持内网UDF传输 * Creation Date 07-08-2008 9:00 * @author 卢俊宇 * @version 1.0 */ public class TransferServer { /** * @param args[0] 端口默认2008(例: 2008) * @param args[1] 接收文件存放路径,默认:和FileServer同一目录\ServerReceive * (例:x:\example\example\) */ public static void main(String[] args) { try { int serPort = 2008;//服务器默认端口2008 String tempFolder = System.getProperty("user.dir")+"\\ServerReceive";//临时文件夹,用于存放接收文件 ServerSocket ss = null;//设定Socket if (args.length<1 || null==args) { ss = new ServerSocket(serPort); }else { //检测输入端口是否正确 if (args[0].replaceAll("\\D", "")!="") { serPort = Integer.parseInt(args[0].replaceAll("\\D", "")); }else { System.out.println("输入的端口有错误,使用系统默认端口"); } ss = new ServerSocket(serPort); if (args[1].length()>0) { tempFolder = args[1]; } } System.out.println("Welcome to TransferServer"); System.out.println("服务器启动,监听端口" + ss.getLocalPort()); System.out.println("服务器临时文件路径: "+tempFolder); while (true) { Socket s = ss.accept(); new Thread(new ServerThread(s,tempFolder)).start(); } } catch (IOException e) { e.getMessage(); System.out.println("服务器端口被占用,或其他问题."); } } } /** * Description 服务器线程 * @author 卢俊宇 * @param tempFolder 接收文件存放路径,默认:TransferServer.class所在目录\ServerReceive * (例:x:\example\example\) * @version 1.1 */ class ServerThread implements Runnable { Socket s;// 实例化socket类 private String tempFolder;//临时文件夹名 public ServerThread(Socket s,String tempFolder) { this.s = s; this.tempFolder = tempFolder; } @SuppressWarnings("deprecation") public void run() { try { InputStream ins = s.getInputStream(); OutputStream outs = s.getOutputStream(); DataInputStream dis = new DataInputStream(ins); DataOutputStream dos = new DataOutputStream(outs); // 取得线程ID String SerID = "SerID-" + Thread.currentThread().getId(); while (true) { try { String inStr = dis.readUTF(); // 接收到的文件包含头信息 if (inStr != null) { // 对收到的socket包过滤出文件信息 if (inStr.contains("ClientInfo")) { System.out.println(SerID + " get FileInfo! "); // 文件名字 String fName = new String(inStr.replaceAll( "(.+)|(<\\/FileName>\\S+)", "") .toString().getBytes("utf-8"), "utf-8"); // 文件总长度 String fSize = new String(inStr.replaceAll( "(.+ )|<\\/FileLength>", "") .toString().getBytes("utf-8"), "utf-8"); System.out.println("size: " + fSize); long Size = Long.parseLong(fSize); // 区块起始长度 String fPs = new String( inStr .replaceAll( "(.+ )|( \\S+)", "").toString().getBytes( "utf-8"), "utf-8"); System.out.println("PS: " + fPs); // 区块结束长度 String fPe = new String( inStr .replaceAll( "(.+)|( \\S+)", "").toString().getBytes( "utf-8"), "utf-8"); System.out.println("PE: " + fPe); long PointS = Long.parseLong(fPs); // 分块头 long PointE = Long.parseLong(fPe); // 分块尾 System.out.println("SourceFile Name :" + fName); File tempF = new File(tempFolder, fName); if (!tempF.exists()) { //检测目标文件夹是否存在 if (new File(tempFolder).isDirectory()) { TempFile.creat(tempF, Size);// 如果临时文件不存在就建立 }else { boolean creat = new File(tempFolder).mkdirs(); if (creat) { TempFile.creat(tempF, Size);// 如果临时文件不存在就建立 }else { System.out.println("Error:System can not creat folder!"); System.out.println(SerID+" exits"); dis.close();// 关闭包类 dos.close();// 关闭输出流 s.close();// 关连接 Thread.currentThread().stop(); } } } // 返回服务器准备好了 String SerReady = SerID + " ServerReady=1"; dos.writeUTF(SerReady);// 返回服务器信息 dos.flush(); // 取得客户端发送标志"SendStart" if (dis.readUTF().equals("SendStart")) { // 随机读写文件(适应多线程方式) RandomAccessFile fos = new RandomAccessFile( tempF.getPath(), "rw"); long curPoint = PointS;// 文件指针起点 long endSet = PointE;// 文件指针终点 long nowSize = 0;// 已读/写字节 byte[] buffer = new byte[1024]; // 建立缓冲区 while (curPoint < endSet) { int length = 0; try { if ((endSet - curPoint + 1) < 1024) { fos.seek(curPoint);// 寻找写入位置 byte[] bufferM = new byte[(int) (endSet - curPoint + 1)];// 调整缓冲区大小 length = ins.read(bufferM);// 读取bufferM缓冲socket流 try { fos.write(bufferM);// 将取得的socket流写入文件 dos.writeUTF("SerGotIt");// 返回服务器信息 dos.flush(); curPoint += length;// 文件指针增加 nowSize += length; fos.close(); // 向发送接收结束标志 dos.writeUTF("ReciveEnd"); dos.flush(); System.out.println(SerID + " is receive ok."); break; } catch (IOException e) { e.printStackTrace(); } } else { fos.seek(curPoint); length = ins.read(buffer); } } catch (IOException e) { e.printStackTrace(); System.out.println(SerID + " is abnormally closed."); break; } if (length == buffer.length) { // 将缓冲区字节写入文件 try { System.out .println(SerID + " receive " + buffer.length + " bytes."); fos.write(buffer); dos.writeUTF("SerGotIt");// 返回服务器信息 dos.flush(); curPoint += buffer.length;// 指针+1024 nowSize += buffer.length; System.out.println(SerID + " 指针位置 " + curPoint); System.out.println(SerID + "线程size写入进度:" + nowSize); } catch (IOException e) { e.printStackTrace(); } } } } } } // 接收到客户端结束标志,跳出循环 if (dis.readUTF().equals("SendEnd")) { System.out.println("服务器接收完毕"); break; } } catch (SocketException s) { // s.printStackTrace(); // 客户端非正常退出处理 System.out.println(SerID + " is abnormally closed."); break; } } dis.close();// 关闭包类 dos.close();// 关闭输出流 s.close();// 关连接 System.out.println(SerID + " exited."); } catch (IOException e) { e.printStackTrace(); } } }
文件传输客户端
-----------------------------------------------------------
package FileServer; 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; import java.net.InetAddress; import java.net.UnknownHostException; import java.text.SimpleDateFormat; import java.util.Date; /** * Description Socket文件传输客户端(默认支持多线程传输,未支持断点续传,未支持内网UDF传输) * Creation Date 07-08-2008 9:00 * @author 卢俊宇 * @version 1.0 */ public class TransferClient { /** * Description 文件传输客户端 * * @param args[0] * 文件路径+文件名(例:x:\example\example.class) * @param args[1] * 服务器IP地址(例: 192.168.1.1) * @param args[2] * 端口默认2008(例: 2008) * @param args[3] * 区块长度默认5 (例: 5) */ public static void main(String[] args) { int serPort = 2008;// 默认连接端口2008; int blockNum = 5;// 文件区块数量(同时决定线程数) String serIP = "192.168.1.105";// 服务器IP String filePath = "e:\\1.rar";// 欲发送文件路径+文件名 if (args.length<1 || null==args) { System.out.println("采用默认配置连接"); } else { if (args[0].length()>0) { filePath = args[0]; } if (args[1].length()>0) { serIP = args[1]; } if (args[2].length()>0) { serPort = Integer.parseInt(args[2]); } if (args[3].length()>0) { blockNum = Integer.parseInt(args[3].replaceAll("\\D", "")); } } System.out.println("文件路径: "+filePath); System.out.println("连接IP: "+serIP); System.out.println("连接端口: "+serPort); System.out.println("线程数: "+blockNum); // 取得文件信息 File source = new File(filePath); if (!source.exists()) { System.out.println("要传输的文件不存在!"); System.exit(0); } long fSize = source.length(); // 文件长 SimpleDateFormat sdf = new SimpleDateFormat("yyMMddhhmmss"); String currentTime = sdf.format(new Date()); String fName = currentTime + Math.round(100) + "-" + source.getName();// 按时间生成文件名 System.out.println("源文件长度 " + fSize+" bytes."); // 区块信息 long blockSize = fSize / blockNum; // 区块长度 String[] fInfo = new String[blockNum];// 按区块生产文件信息组 long offset = 0;// 区块起点位置 long endset = 0;// 区块终点位置 String sourceFilePath = source.getPath();// 取源文件路径 // 打包区块信息 for (int i = 0; i < blockNum; i++) { offset = ((long) i) * blockSize;// 设置文件指针起点 endset = (((long) i + 1) * blockSize - 1 + (i == blockNum - 1 ? fSize % blockNum : 0));// 设置文件指针终点 fInfo[i] = "ClientInfo" + fName + " "; fInfo[i] += "" + offset + " "; fInfo[i] += "" + endset + " "; fInfo[i] += "" + fSize + " "; // 按区块开启线程 new Thread(new FileTransThread(fInfo[i], sourceFilePath, offset, endset, serIP, serPort)).start(); } } } /** * Description 文件传输线程 * * @author 卢俊宇 * @param info; * 初始化时打包的文件信息 * @param sourceFilePath * 文件路径+文件名(例:x:\example\example.class) * @param offSet * 文件指针起点值地址(按文件区块数量划分) * @param endSet * 文件指针终点值地址(按文件区块数量划分) * @param serPort * 默认连接端口2008; * @param serIP * 连接IP * @version 1.1 */ class FileTransThread implements Runnable { private String info;// 文件信息 private String sourceFilePath;// 源文件路径 private long offSet;// 这个线程写入文件起始值地址 private long endSet;// 这个线程写入的文件长度 private int serPort;// 默认连接端口2008; private String serIP;// 连接IP FileTransThread(String info, String sourceFilePath, long offSet, long endSet, String serIP, int serPort) { this.info = info; this.sourceFilePath = sourceFilePath; this.offSet = offSet; this.endSet = endSet; this.serIP = serIP; this.serPort = serPort; } public void run() { try { String CliID = "ClientID-" + Thread.currentThread().getId(); System.out.println(CliID + " connect " + serIP); Socket s = new Socket(InetAddress.getByName(serIP), serPort); System.out.println(CliID + " successfully connected."); InputStream clientIn = s.getInputStream(); OutputStream clientOut = s.getOutputStream(); DataInputStream dis = new DataInputStream(clientIn); DataOutputStream dos = new DataOutputStream(clientOut); dos.writeUTF(info);// 发送文件信息到服务器 dos.flush(); System.out.println(CliID + " send FileInfo!"); while (true) { String inStr = dis.readUTF(); // 判断服务器是否准备接收 if (inStr.contains("ServerReady=1")) { System.out.println(CliID + " report: " + inStr); // 开始准备文件传输 dos.writeUTF("SendStart");// 发送接收标志 dos.flush(); RandomAccessFile fos = new RandomAccessFile(sourceFilePath, "r"); long curPoint = offSet; long nowSize = 0; byte[] buffer = new byte[1024]; while (curPoint < endSet) { // 建立缓冲区 int length = 0; try { if ((endSet - curPoint + 1) < 1024) { fos.seek(curPoint); byte[] bufferM = new byte[(int) (endSet - curPoint + 1)];// 调整缓冲区大小 length = fos.read(bufferM); try { clientOut.write(bufferM); clientOut.flush(); //等待服务器确认 for(;;){ if (dis.readUTF().equals("SerGotIt")) { break; } } curPoint += length; nowSize += length; fos.close(); System.out.println(CliID + " is send ok."); break; } catch (IOException e) { e.printStackTrace(); System.out.println(CliID + " is abnormally closed."); break; } } else { fos.seek(curPoint); length = fos.read(buffer); } } catch (IOException e) { e.printStackTrace(); } if (length == buffer.length) { // 将缓冲区字节写入文件 try { System.out.println(CliID + " send " + buffer.length + " bytes."); clientOut.write(buffer); clientOut.flush(); //等待服务器确认 for(;;){ if (dis.readUTF().equals("SerGotIt")) { break; } } curPoint += buffer.length;// 指针+1024 nowSize += buffer.length; System.out.println(CliID + " 指针位置 " + curPoint); System.out.println(CliID + "线程size读入进度:" + nowSize); } catch (IOException e) { e.printStackTrace(); System.out.println(CliID + " is abnormally closed."); break; } } } } // 向服务端发送结束标志,跳出循环 if (dis.readUTF().equals("ReciveEnd")) { dos.writeUTF("SendEnd"); dos.flush(); System.out.println("传输完毕"); break; } } dis.close();// 关闭包类 dos.close();// 关闭输出流 s.close();// 关连接 } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } 生成临时文件 package FileServer; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; /** * Description 生成临时文件 * Creation Date 07-08-2008 9:00 * @author 卢俊宇 * @version 1.0 */ public class TempFile { /** * 创建文件 * @param targetFile 文件对象 * @param fileLength 文件字节长度 */ public static void creat(File targetFile, long fileLength) { long now = System.currentTimeMillis(); long length = fileLength;//指定写入文件文件大小 byte[] buffer = new byte[1024];// 缓冲区1024 bytes FileOutputStream fos; try { fos = new FileOutputStream(targetFile); while (true) { // 建立缓冲区 if (length > 1024) { // 将缓冲区字节写入文件 try { fos.write(buffer);// 写入缓冲 length = length - 1024; } 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; } } System.out.println("写入临时文件" + targetFile.getName() + ":" + targetFile.length() + " bytes"); } catch (FileNotFoundException e1) { e1.printStackTrace(); } long end = System.currentTimeMillis(); System.out.println("临时文件" + targetFile.getName() + "写入耗时:" + (end - now) + " ms"); } }
-文件传输包含3个类---------------------------------------------------
效果:我已经测试过该程序了,能成功运行!可以多线程
FileServer.rar (5.9 KB)
描述: java源文件
下载链接: http://dl.iteye.com/topics/download/f28c97a6-91c2-391a-ad95-8fba65a2e088