客户端通过TCP/IP协议从服务端获取想要的文件
程序员文章站
2022-04-15 19:21:55
客户端通过TCP/IP从服务端获取想要的文件通过TCP/IP协议传输文件比较安全,传输过程中不会丢失文件数据,所以传输文件我们不用UDP协议。 (让我们来分析一下,这个程序使用TCP/IP协议如何传输所需文件。如图所示,左边为客户端,右边为服务端。 一、服务端要将文件列表发给客户端,由于文件传输不能直接传输内容,只能通过将文件对象序列化之后,传递文件列表信息。此时客户端要接受被序列化的文件后,将其反序列化,得到文...
客户端通过TCP/IP从服务端获取想要的文件
通过TCP/IP协议传输文件比较安全,传输过程中不会丢失文件数据,所以传输文件我们不用UDP协议。
(让我们来分析一下,这个程序使用TCP/IP协议如何传输所需文件。
如图所示,左边为客户端,右边为服务端。
一、服务端要将文件列表发给客户端,由于文件传输不能直接传输内容,只能通过将文件对象序列化之后,传递文件列表信息。此时客户端要接受被序列化的文件后,将其反序列化,得到文件列表信息。传输过程中,我们给文件编号,用map传输文件列表数据,其中map的键为所需下载文件序号,map值问文件的名称;
二、根据传来文件的序号,客户选择文件序号,将文件序号传递给服务端,服务端得到map的键之后,根据键获得值(所需文件的名称),准备传输文件。
三、根据文件名称,和所下载的文件夹路径结合创建名字相同的文件,开始传输文件。
注意:服务端一定要用多线程模式,放入客户端,不然一旦某个客户端出现异常,就会导致整个服务器堵塞崩溃。
传输示图:
具体实现步骤:
服务端:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Scanner;
/**
* 文件服务器的服务端
*
* @param args
* @throws IOException
*/
public class FileServer extends Thread {
private File source;
private Socket s;
public FileServer(File source, Socket s) {
this.source = source;
this.s = s;
}
@Override
public void run() {
try {
/**************1.发送文件列表***********/
// 获取基于socket对象的输出流
ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
//获取文件列表
File[] files = source.listFiles();
//建map集合,文件序号表示键,文件对象作为值
HashMap<String, File> map = new HashMap<>();
for (int i = 0; i < files.length; i++) {
// 将文件序号(从0开始)
map.put(String.valueOf(i), files[i]);
}
//将map集合发送到客户端
oos.writeObject(map);
oos.flush();
/******2.接受客户端发送的文件序号********/
Scanner sc = new Scanner(s.getInputStream());
String num = sc.nextLine();
System.out.println("客户端需要下载的文件编号:"+num);
/**********3.文件传输**********/
File file =map.get(num);
//获取文件的输出流
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis =new BufferedInputStream(fis);
//获取基于socket的输出流
BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
//传输
TransferUtils.transfer(bis, bos);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
// 准备需要对外提供的文件资源
File source = new File("F:\\英雄时刻\\38123882");
// 占据指定串口 创建服务器(1024-49151)
ServerSocket ss = new ServerSocket(8888);
System.out.println("服务器已开启,等待连接");
// 开启循环监听
while (true) {
// 监听并获取其中一个客户端通信的Socket对象
Socket s = ss.accept();
System.out.println("客户端连接:"+s.getInetAddress().getHostAddress());
// 创建并且启动线程
new FileServer(source, s).start();
}
}
}
客户端:
package com.softeem.lesson39;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Scanner;
import javax.swing.filechooser.FileSystemView;
public class FileClient {
private String fileName;
public String getFileName() {
return fileName;
}
/**
* 发送文件序号
* @throws IOException
*/
public void sendNum(HashMap<String,File> map,Socket s ) throws IOException{
System.out.println("请输入需要下载的文件序号:");
Scanner sc = new Scanner(System.in);
String num =sc.nextLine();
//如果输入的序号没有包含在map的键集中,则递归调用,重新输入序号
if(!map.containsKey(num)) {
System.out.println("没有该序号对应的文件!");
sendNum(map,s);
return;
}
//获取文件名称 给全局变量
fileName = map.get(num).getName();
//基于socket的输出流
PrintWriter pw =new PrintWriter(s.getOutputStream());
pw.println(num);
pw.flush();
}
/**
* 客户端
* @param args
* @throws IOException
* @throws UnknownHostException
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws UnknownHostException, IOException, ClassNotFoundException {
FileClient fc =new FileClient();
//建立连接
Socket s = new Socket("192.168.7.141",8888);
//接受文件列表
ObjectInputStream ois =new ObjectInputStream(s.getInputStream());
Object obj =ois.readObject();
//将对象转换为Map集合
HashMap<String,File> map=(HashMap<String,File>)obj;
//对map遍历
map.forEach((k,v)->{
System.out.println(k+"."+v.getName());
});
/*******2.发送需要下载的文件序号********/
fc.sendNum(map, s);
/********3.接受文件**********/
String fname = fc.getFileName();
System.out.println("准备下载:"+fname);
//获取与本机有关文件系统预览
FileSystemView fsv =FileSystemView.getFileSystemView();
//获取桌面目录
File desketop = fsv.getHomeDirectory();
//根据获取的桌面目录以及文件名组合一个新的file对象
File target = new File(desketop,fname);
//获取文件的输出流
OutputStream os =new FileOutputStream(target);
//获取网络中的输出流
InputStream is = s.getInputStream();
//文件传输
TransferUtils.transfer(is, os);
System.out.println("下载完成!");
}
}
输入流向输出流传输工具代码:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* 传输工具类
* @author Keerloo
*
*/
public class TransferUtils {
/**
* 将输入流的数据通过输出流输出
* @param in
* @param out
* @throws IOException
*/
public static void transfer(InputStream in ,OutputStream out) throws IOException {
try{
byte[] b = new byte[1024];
int len = 0;
while((len=in.read(b))!=-1) {
out.write(b, 0, len);
}
}finally {
if(out!=null)out.close();
if(in!=null)in.close();
}
}
}
文件信息:
本文地址:https://blog.csdn.net/qq1131610682/article/details/107594219
上一篇: 插入排序与冒泡排序的实现区别 附代码讲解
下一篇: 微服务和分布式的区别以及微服务框架介绍