# 编程实现 ftp 服务器
## 一、开发、运行环境说明
1. 开发工具:IntelliJ IDEA
2. 开发环境: JDK1.8
3. 运行环境:IDEA(服务端) 和 windows 黑窗口(客户端)
## 二、系统实现的功能:
(1)客户端通过 Windows 的命令行访问 FTP 服务器。
(2)FTP 服务器可以并发地服务多个客户。
(3)实现对 FTP 命令 user、pass、dir、get、upload 五个命令的支持。
(4)对出现的问题或错误做出响应。
## 三、系统工程设计
1.工程结构的截图:
![](https://www.writebug.com/myres/static/uploads/2021/10/27/d74791b259ccb3c1c63c014ce2782661.writebug)
2.主要实现技术:
(1) 通过 Socket 编程实现通信
(2) 通过 Java 线程池实现多线程并发访问
(3) 使用了工厂设计模式
(4) 对用户密码使用 md5 加密
3.关键代码实现:
```java
// 线程池工具类
public class ThreadUtil {
private static ThreadPool mThreadPool;
public static ThreadPool getThreadPool() {
if (mThreadPool == null) {
synchronized (ThreadUtil.class) {
if (mThreadPool == null) {
int cpuCount = Runtime.getRuntime().availableProcessors();// 获取cpu数量
System.out.println("cpu个数:" + cpuCount);
int threadCount = 10;
mThreadPool = new ThreadPool(threadCount, threadCount, 0l);
}
}
}
return mThreadPool;
}
// 线程池
public static class ThreadPool {
private int corePoolSize;// 核心线程数
private int maximumPoolSize;// 最大线程数
private long keepAliveTime;// 休息时间
private ThreadPoolExecutor executor;
private ThreadPool(int corePoolSize, int maximumPoolSize,
long keepAliveTime) {
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.keepAliveTime = keepAliveTime;
}
public void execute(Runnable r) {
if (executor == null) {
executor = new ThreadPoolExecutor(corePoolSize,
maximumPoolSize, keepAliveTime, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(),
Executors.defaultThreadFactory(), new AbortPolicy());
// 参1:核心线程数;参2:最大线程数;参3:线程休眠时间;参4:时间单位;参5:线程队列;参6:生产线程的工厂;参7:线程异常处理策略
}
executor.execute(r);
}
// 取消任务
public void cancel(Runnable r) {
if (executor != null) {
// 从线程队列中移除对象
executor.getQueue().remove(r);
}
}
}
}
// user命令
public class UserCommmand implements BaseCommand {
private BufferedReader reader;
@Override
public void executeCommand(String userName, BufferedWriter writer, UserInfo userInfo) {
if (AccountUtil.hasUsername(userName)) {
System.out.println("The account is exist! "+userName);
try {
writer.write("n331rn");
writer.flush();
userInfo.setUsername(userName);
//reader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
}else{
System.out.println("The account is not exist! "+userName);
try {
writer.write("501rnn");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// pass命令,密码验证
public class PassCommand implements BaseCommand {
@Override
public void executeCommand(String passWord, BufferedWriter writer, UserInfo userInfo) {
String passWord2Md5 = Md5Util.encoder(passWord);
if (passWord2Md5.equals(AccountUtil.getPassword(userInfo.getUsername()))) {
System.out.println("密码正确"+passWord + ",md5密码:"+passWord2Md5);
try {
writer.write("n 230 PWD is right!Welcome!rn");
writer.flush();
userInfo.setPassword(passWord2Md5);
} catch (IOException e) {
e.printStackTrace();
}
}else{
try {
writer.write("n 530 Wrong PWD!rn");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// dir文件列表命令
public class DirCommand implements BaseCommand {
/
* dir功能实现
* @param datas
* @param writer
* @param userInfo
*/
@Override
public void executeCommand(String datas, BufferedWriter writer, UserInfo userInfo) {
File file = new File(AccountUtil.getRootPath());
if (!file.isDirectory()) {
try {
writer.write("n 210 The file is not existrn");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}else{
//拼接文件目录字符串
StringBuffer dirList = new StringBuffer();
int count = 1;
for(String item:file.list()){
File itemFile = new File(file+File.separator+item);
String size = FileUtil.getFileSize(itemFile);
if (size.equals("")||size==null) {
size = "dir";
}else{
size += " file";
}
dirList.append(count+" "+item+" "+size);
dirList.append("rn");
count++;
}
try {
writer.write("n 150 open ascii mode...rn");
writer.flush();
writer.write(dirList + "rn");
writer.write("220 transfer complete...rn");
writer.flush();
System.out.println(dirList.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// 文件上传upload命令
public class UploadCommand implements BaseCommand {
/
* 文件上传
* @param datas
* @param writer
* @param userInfo
*/
@Override
public void executeCommand(String datas, BufferedWriter writer, UserInfo userInfo) {
File file = new File(AccountUtil.getRootPath());
try{
writer.write("n 150 Binary data connectionrn");
writer.flush();
File lastFileName = new File(AccountUtil.getRootPath()+"/"+datas);
String name = AccountUtil.getRootPath()+datas;
for (String item:file.list()){
item = AccountUtil.getRootPath()+item;
//获取相同文件名
if (item.equals(name)){
//将文件名改成时间戳
File temp = new File(AccountUtil.getRootPath()+ Calendar.getInstance().getTimeInMillis()+"."+item.substring(item.lastIndexOf(".")+1));
lastFileName.renameTo(temp);
System.out.println(lastFileName);
}
}
RandomAccessFile inFile = new RandomAccessFile(lastFileName,"rw");
// 开始上传
Socket tempSocket = new Socket("127.0.0.1",25);
InputStream inSocket = tempSocket.getInputStream();
byte byteBuffer[] = new byte[1024];
int length;
while((length =inSocket.read(byteBuffer) )!= -1){
inFile.write(byteBuffer, 0, length);
}
System.out.println("transfer complete");
inFile.close();
inSocket.close();
tempSocket.close();
//传输结束
writer.write("n226 upload successrn");
writer.flush();
}
catch(IOException e){
e.printStackTrace();
}
}
}
// 文件下载get命令
public class GetCommand implements BaseCommand {
@Override
public void executeCommand(String datas, BufferedWriter writer, UserInfo userInfo) {
File file = new File(AccountUtil.getRootPath()+File.separator+datas);
File rootFile = new File(System.getProperty("user.home")+File.separator);
File lastFileName = new File(System.getProperty("user.home")+File.separator+datas);
String name = System.getProperty("user.home")+""+datas;
if (file.exists()) {
// 检测是否有相同的文件名
for (String item:rootFile.list()){
item = System.getProperty("user.home")+""+item;
// 获取相同文件名
if (item.equals(name)){
// 如果有则改掉将文件名改成时间戳
File temp = new File(System.getProperty("user.home")+""+ Calendar.getInstance().getTimeInMillis()+"."+item.substring(item.lastIndexOf(".")+1));
lastFileName.renameTo(temp);
}
}
try {
writer.write("150 open ascii mode...rn");
writer.flush();
Socket socket = new Socket("127.0.0.1", 25);
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
系统实现的功能: (1)客户端通过 Windows 的命令行访问 FTP 服务器。 (2)FTP 服务器可以并发地服务多个客户。 (3)实现对 FTP 命令 user、pass、dir、get、upload 五个命令的支持。 (4)对出现的问题或错误做出响应。
资源推荐
资源详情
资源评论
收起资源包目录
100012933-基于Java实现的(控制台)文件传输服务器.zip (24个子文件)
ftpwork
src
com
chenzhichao
www
ftp
utils
AccountUtil.java 943B
ThreadUtil.java 2KB
FileUtil.java 825B
Md5Util.java 1KB
command
BaseCommand.java 244B
CommanFactory.java 561B
impl
UploadCommand.java 2KB
GetCommand.java 2KB
UserCommmand.java 1KB
PassCommand.java 1KB
DirCommand.java 2KB
entity
UserInfo.java 781B
server
FtpServer.java 986B
TestMD5.java 382B
ClientConnection.java 2KB
LICENSE 1KB
.idea
misc.xml 273B
inspectionProfiles
Project_Default.xml 1KB
modules.xml 246B
.gitignore 176B
encodings.xml 1KB
ftp.iml 423B
陈智超-编程实现文件传输服务器.doc 327KB
README.md 11KB
共 24 条
- 1
资源评论
神仙别闹
- 粉丝: 2706
- 资源: 7641
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功