您的位置:首页 > 理论基础 > 计算机网络

Java网络编程实践和总结 --- 基于TCP的Socket编程之实现文件上传和下载服务

2015-04-01 19:28 1241 查看
通过上一篇blog的学习和练习总结,我们大概掌握了Socket的TCP编程,也大概掌握了客户端和服务端的编程的实现方式。

通过Echo程序的实现,我们可以很好的理解Socket编程时数据传输时输入和输出流的操作。

接下来我们进一步学习和练习,通过简单的实现一个文件下载和上传软件来进一步加深和巩固网路编程的知识。

实例二:文件上传和下载服务程序:

TextServer为服务端:TextServer的内部内TextServer.UploadFileHandler线程用于处理客户端上传文件的请求,TextServer的内部内TextServer.DownloadFileHandler线程用于处理客户端下载文件的请求。

服务端的main()方法为服务端循环监听入站操作并且判断客户端的操作类型,再启动不同的服务线程来为客户端服务。

TextClient为客户端:TextClient.UploadFileHandler线程用于处理上传操作,TextClient.DownloadFileHandler线程用于处理下载操作。

客户端的main()方法为用于界面的操作,根据客户选择来启动不同的操作。

以下为客户端:

public class TextClient {

public static void main(String[] args) {
//从标准输入当中读取操作选项
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//操作选项
String selection = null;
//上传文件,全路径
String uploadFile = null;
//在服务器端存放的下载文件名
String downloadFile = null;
//文件下载的目的路径
String donwloadPath = null;

while (true) {
//简单的操作说明界面
System.out.println(">>>>> File Operation : please input selection <<<<<");
System.out.println("1 : upload file");
System.out.println("2 : download file");
System.out.println("3 : quit");

try {
//从标准输入当中获取选项:1, 2, 3
selection = br.readLine();
//输入为3时推出操作
if ("3".equals(selection)) {
System.out.println("===> quit!");
break;

//输入为1时上传文件操作
} else if ("1".equals(selection)) {
System.out.print("Input upload file : ");
uploadFile = br.readLine();
//上传文件到服务器,启动该操作的线程
System.out.println("client start to upload!");
Thread uploadThread = new UploadFileHandler(uploadFile);
uploadThread.start();
uploadThread.join();
System.out.println("client upload finished!");

//输入为2时上传文件操作
} else if ("2".equals(selection)) {
//输入需要下载的文件
System.out.print("Input download file: ");
downloadFile = br.readLine();
//输入文件下载的目的路径
System.out.print("Input download path : ");
donwloadPath = br.readLine();

//从服务器下载文件,启动该操作的线程
System.out.println("client start to download!");
Thread downloadThread = new DownloadFileHandler(downloadFile, donwloadPath);
downloadThread.start();
downloadThread.join();
System.out.println("client download finished!");
//其他无效的输入项
} else {
System.out.println("Error input, try again!");
}

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}

private static class UploadFileHandler extends Thread {

//客户端Socket
private Socket client;
private String filePath;

public UploadFileHandler(String filePath) {
try {
//需要上传的本地文件
this.filePath = filePath;
//连接到服务器端
this.client = new Socket(TextServer.DEFAULT_SERVER_HOST, TextServer.DEFAULT_SERVER_PORT);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

@Override
public void run() {
//System.out.println("===> UploadFileHandler : ");
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
byte[] buf = new byte[1024];
int len = -1;
try {
//建立文件输入流,读取需要上传的数据
bis = new BufferedInputStream(new FileInputStream(new File(filePath)));
//建立输出流用于将文件数据上传到服务器端
bos = new BufferedOutputStream(client.getOutputStream());

/**
* 发送操作标志:服务器需要判断入站操作时上传文件还是下载文件
* 将操作标志发给服务端解析处理
* TextServer.CLIENT_FILE_UPLOAD : 上传操作
* TextServer.CLIENT_FILE_DOWNLOAD : 下载操作
*/
String uploadsring = TextServer.CLIENT_FILE_UPLOAD + ","+filePath;
byte[] uploadbyte = uploadsring.getBytes();
bos.write(uploadbyte, 0, uploadbyte.length);
bos.flush();

//当发送完操作标识符以后,开始读文件数据,并且往服务端上传数据
while ((len = bis.read(buf)) > 0) {
//System.out.println("len : " + len);
bos.write(buf, 0, len);
bos.flush();
}
//System.out.println("file : " + filePath + " is upload finally!");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (client != null) {
try {
client.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

}

private static class DownloadFileHandler extends Thread {
//客户端Socket
private Socket client;
//需要下载的文件,存放在服务端中
private String downloadFile;
//下载文件的目的路径,本机路径
private String downloadPath;

public DownloadFileHandler(String downloadFile, String downloadPath) {
try {
this.downloadFile = downloadFile;
this.downloadPath = downloadPath;
//建立和服务器的连接
client = new Socket(TextServer.DEFAULT_SERVER_HOST, TextServer.DEFAULT_SERVER_PORT);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

@Override
public void run() {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
BufferedOutputStream sbos = null;

byte[] buf = new byte[1024];
int len = -1;
try {
//从服务器端读取数据的输入流
bis = new BufferedInputStream(client.getInputStream());
//将数据写到目的路径中的输出流
bos = new BufferedOutputStream(new FileOutputStream(new File(downloadPath, downloadFile)));
//用于和服务端传输的输出流
sbos = new BufferedOutputStream(client.getOutputStream());

/**
* 发送操作标志:服务器需要判断入站操作时上传文件还是下载文件
* 将操作标志发给服务端解析处理
* TextServer.CLIENT_FILE_UPLOAD : 上传操作
* TextServer.CLIENT_FILE_DOWNLOAD : 下载操作
*/
String uploadsring = TextServer.CLIENT_FILE_DOWNLOAD + "," +downloadPath + "," + downloadFile;
byte[] uploadbyte = uploadsring.getBytes();
sbos.write(uploadbyte, 0, uploadbyte.length);
sbos.flush();

//发送操作标志以后,等待获取服务端的回复,确认文件是否存在
len = bis.read(buf);
String result = new String(buf, 0, len);
//如果客户端请求文件不存在服务器则退出
if (TextServer.SERVER_FILE_NOTEXIST.equals(result)) {
System.out.println("download file not exist on server!");
return ;
} else {
//文件存在继续执行操作
System.out.println("download file exist on server!");
}

//开始下载文件数据,并且保存到本地路径当中
while ((len = bis.read(buf)) > 0) {
//System.out.println("len : " + len);
bos.write(buf, 0, len);
bos.flush();
}
//System.out.println("file : " + downloadPath + downloadFile + " is download finally!");

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}


以下为服务端:

public class TextServer {
//服务器的主机主机名
public static final String DEFAULT_SERVER_HOST = "127.0.0.1";
//提供服务的端口
public static final int DEFAULT_SERVER_PORT = 8090;
//默认存放文件的工作目录
public static final String DEFAULT_DIRECTORY = "E:\\packages2";
//操作标识符:
public static final String CLIENT_FILE_UPLOAD = "upload";
public static final String CLIENT_FILE_DOWNLOAD = "download";
//文件判断标识
public static final String SERVER_FILE_NOTEXIST = "not existed";
public static final String SERVER_FILE_EXIST = "existed";

//服务端的Socket套接字,用于监听入站请求
private static ServerSocket server;
//客户端的Socket套接字,存放入站Socket
private static Socket client;

static {
try {
//在静态块中初始化服务端Socket
server = new ServerSocket(DEFAULT_SERVER_PORT);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public static void main(String[] args) {

BufferedInputStream bis = null;
BufferedOutputStream bos = null;

//主线程不停循环监听端口的入栈请求
while (true) {
try {
//该方法会阻塞
client = server.accept();
//有入站请求后打印信息
System.out.println("client accepted : " + client.getInetAddress() + " , port : " + client.getPort());
bis = new BufferedInputStream(client.getInputStream());
bos = new BufferedOutputStream(client.getOutputStream());

//以下操作为判断入站的操作类型
byte[] buf = new byte[1024];
int len = -1;
len = bis.read(buf);
String fileOperation = new String(buf, 0, len);
System.out.println("fileOperation : " + fileOperation);
String[] files = fileOperation.split(",");

//如果出站请求为上传文件时,启动上传的线程单独线程服务
if (CLIENT_FILE_UPLOAD.equals(files[0])) {
System.out.println("upload operation : upload");
//开启上传处理线程
Thread uploadThread = new UploadFileHandler(client, bis, bos, fileOperation);
uploadThread.start();
uploadThread.join();
System.out.println("upload ====> done");

////如果出站请求为下载文件时,启动上传的线程单独线程服务
} else if (CLIENT_FILE_DOWNLOAD.equals(files[0])) {
System.out.println("upload operation : download");
//开启下载处理线程
Thread downloadThread = new DownloadFileHandler(client, bis, bos, fileOperation);
downloadThread.start();
downloadThread.join();
System.out.println("donwload ====> done");
} else {

}

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}

private static class UploadFileHandler extends Thread {
private Socket client;
//从客户端读取上传文件数据的输入流
private BufferedInputStream bis;
//客户端的输出流
private BufferedOutputStream bos;
//写入文件的输出流
private BufferedOutputStream fbos;
//文件操作标识
private String fileOperation;

public UploadFileHandler(Socket client, BufferedInputStream bis, BufferedOutputStream bos, String fileOperation) {
this.client = client;
this.bis = bis;
this.bos = bos;
this.fileOperation = fileOperation;
}

@Override
public void run() {

String[] files = fileOperation.split(":");
File file = new File(files[1]);
//获取保存的文件名称
String filename = file.getName();
System.out.println("====> filename : " + filename);

byte[] buf = new byte[1024];
int len = -1;
try {
//建立文件输出流,用于将从客户端上传的数据保存到本地路径上
fbos = new BufferedOutputStream(new FileOutputStream(new File(DEFAULT_DIRECTORY, filename)));
//读取客户端数据并且写入到本地文件上
while ((len = bis.read(buf)) > 0) {
//System.out.println("len : " + len);
fbos.write(buf, 0, len);
fbos.flush();
}
//System.out.println("upload file done : " + filename);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (fbos != null) {
try {
fbos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

}

}

private static class DownloadFileHandler extends Thread {
private Socket client;
private BufferedInputStream bis;
private BufferedOutputStream bos;
private BufferedInputStream fbis;
private String fileOperation;

public DownloadFileHandler(Socket client, BufferedInputStream bis, BufferedOutputStream bos, String fileOperation) {
this.client = client;
this.bis = bis;
this.bos = bos;
this.fileOperation = fileOperation;
}

@Override
public void run() {

byte[] buf = new byte[1024];
int len = -1;

try {
//解析文件操作标识,获取客户端下载的文件名
String donwloadFile = fileOperation.split(",")[2];
System.out.println("downloadFile : " + donwloadFile);
File file = new File(DEFAULT_DIRECTORY, donwloadFile);
System.out.println("file : " + file);

//判断文件是否存在,当文件不存在时线程结束
if (!file.exists()) {
String result = "not existed";
bos.write(result.getBytes(), 0, result.getBytes().length);
bos.flush();
System.out.println("downloadFile is not existed!");
return ;

//文件存在是继续操作
} else {
fbis = new BufferedInputStream(new FileInputStream(file));
String result = "existed";
bos.write(result.getBytes(), 0, result.getBytes().length);
bos.flush();
System.out.println("downloadFile is existed!");
}

//开始从本地读取文件数据,并且发给客户端
while ((len = fbis.read(buf)) > 0) {
//System.out.println("len : " + len);
bos.write(buf, 0, len);
bos.flush();
}

//System.out.println("downloadFile is done!");

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (fbis != null) {
try {
fbis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

}

}

}


测试结果:

E:\packages为客户端的工作目录,该目录只有文件1.jpg

E:\packages为服务端的工作目录,该目录只有文件2.jpg

上传文件测试:

客户端结果:



服务端结果:



下载文件测试:

客户端结果:



服务端结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: