一、利用socket实现文件传输断点续传
实现方法
采用的方法是在客户端传输失败之后服务器保持当前存储的位置信息,在下一次客户端发送这个数据时,读取位置信息,发送给客户端让客户端从断点处发送数据
改善
这段代码有很多bug,也有很多需要完善的地方用户体验不好,以后在加以修改,例如:应当以命令的方式请求服务器,验证有验证的命令,发送数据有发送数据的命令,发送文件基本信息的命令
服务器端
public class server {
public static void main(String[] args) throws IOException{
int sum=0;//记录读取位置断点续传
String fileName=null;
//BufferedWriter writer=null;
RandomAccessFile rdf=null;
ServerSocket serverSocket=new ServerSocket(8888);
Socket socket=serverSocket.accept();//监听
//读取数据
BufferedReader dataIn=new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedWriter dataout=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String data=null;
StringBuffer strBuf=new StringBuffer();
while((data=dataIn.readLine())!=null){
if(data.contains("Eof")) {//读到Eof结束
break;
}
strBuf.append(data);//添加到bufferedReader数组中
}
fileName=strBuf.toString();//第一次发送的是文件名
System.out.println("开始接收数据");
//
//开始接收数据
//
rdf=new RandomAccessFile(new File(fileName), "rw");
char[] cbuf=new char[512];//传输文件数据一次传输512B
int len;
//发送验证信息断点续传,先保存位置再发送给客户端
dataout.write(len=rdf.readInt());
dataout.write("Eof"+"\n");
dataout.flush();
rdf.seek(len);//进行移动
try{
while((len=dataIn.read(cbuf, 0, 512))!=-1){
rdf.writeBytes(new String(cbuf,0,len));
sum=sum+len;
}
System.out.println("数据传输完成");
}catch(Exception ex){
System.out.println("数据传输错误");
}
rdf.seek(0);
rdf.writeLong(sum);//在头部添加位置信息,其实应该在和他名字相同的文件中添加信息
//关闭
rdf.close();
dataIn.close();
dataout.close();
socket.close();
}
}
功能模块没有分开,应该以命令方式执行,在保存位置的时候不应该在源文件中保存数据应该重新创建一个状态文件,将文件的信息、但前读取大小等信息一一写入进去
客户端
package socket;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.RandomAccessFile;
import java.net.Socket;
import java.net.UnknownHostException;
public class client {
public static void main(String[] args) throws UnknownHostException, IOException {
// TODO Auto-generated method stub
boolean flag=false;
String path="e:\\test.txt";
//String path="E:\\安装包\\jdk-8u101-windows-x64.exe";
RandomAccessFile reader=new RandomAccessFile(new File(path), "r");
Socket socket=new Socket("127.0.0.1",8888); //连接数据库
//
//传输文件基本信息
//
BufferedWriter netWriter=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
netWriter.write(path.substring(path.lastIndexOf("\\")+1,path.length())+"\n");
netWriter.write("Eof"+"\n");
//写文件完成Eof结束
netWriter.flush();
//
//读取服务器发送数据
//
BufferedReader dataIn=new BufferedReader(new InputStreamReader(socket.getInputStream()));
int dataint=0;
String data=null;
StringBuffer strBuf=new StringBuffer();
dataint=dataIn.read();
flag=true;
reader.seek(dataint);//设置断点处坐标
//
//发送文件数据
//
if(flag){
netWriter=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));//传输数据
byte[] cbuf=new byte[512];//传输文件数据一次传输512B
String len;
while((len=reader.readLine())!=null){
netWriter.write(len);
netWriter.flush();
}
reader.close();
}
System.out.println("传输完成");
netWriter.close();
dataIn.close();
socket.close();
}
}
同服务器端一样太乱了,慢慢加以修改
二、序列化、反序列化和网络序列化
public class main {
public static void main(String[] args) throws ClassNotFoundException, IOException, InterruptedException {
// TODO Auto-generated method stub
objectSer();
objectAnSer();
NetAnSer();
}
//
//序列化函数
//
public static void objectSer(){
ObjectOutputStream out;
try {
out = new ObjectOutputStream(new FileOutputStream("test.txt"));//序列化
out.writeObject(new Mytest("tang", "man", "201430185022"));
out.writeObject(new Mytest("tang1", "man", "20143018"));
out.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//
//反序列化函数
//
public static void objectAnSer(){
ObjectInputStream in;
Mytest myTest=null;
try {
in = new ObjectInputStream(new FileInputStream("test.txt"));//反序列化
myTest = (Mytest)in.readObject();
in.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(myTest.name);
System.out.println(myTest.sex);
}
//
//网络反序列化函数
//
public static void NetAnSer() throws IOException, ClassNotFoundException, InterruptedException{
ServerSocket serverSocket=new ServerSocket(9999);
Socket socket=serverSocket.accept();//开始监听
System.out.println("good");
//接收客户端发来的序列化数据
ObjectInputStream objectReader=new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));
//读取数据
Object ob=objectReader.readObject();
Mytest mytest=null;
if(ob==null)
System.out.println("error");
else
mytest=(Mytest)ob;
System.out.println(mytest.id);
objectReader.close();
}
}
客户端
public static void main(String[] args) throws IOException {
Socket socket=new Socket("127.0.0.1", 9999);
ObjectOutputStream writer=new ObjectOutputStream(socket.getOutputStream());
Mytest myTest=new Mytest("tangbo", "tangbo","tangbo");
writer.writeObject(myTest);
writer.flush();
writer.close();
}
}
数据结构
public class Mytest implements Serializable
{
transient String name;//序列化时阻止该变量被序列化到文件中
String sex;
String id;
public Mytest(String name,String sex,String id) {
// TODO Auto-generated constructor stub
this.name=name;
this.sex=sex;
this.id=id;
}
}
三、总结
经过这次作业我了解到断点续传,并按照思路写出具体的代码,但还有很多需要改进的地方,这还不能算是一个网络传输文件的程序,有太多需要修改的地方,这次作业我学到了很多东西