java 简单的文件上传下载服务器模型(NIO 版本)

来源:互联网 发布:dj网络歌手 编辑:程序博客网 时间:2024/05/21 10:51

前面写了一篇文章是基于IO+多线程的文件上传下载服务器模型,这篇文章是它的后续,基于NIO实现文件的上传下载功能。

服务端的代码:

package com.myftpnio.server;import java.net.InetSocketAddress;import java.net.ServerSocket;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.util.Iterator;import com.myftpnio.handler.NioHandler;import com.myftpnio.handler.ServerHandler;public class FtpNioServer {public static final int PORT = 5000;public static int connum = 0;public static final int MAX = 5000;public static final String ROOT = "D:/FtpDir/";public static void main(String argv[]) {try {Selector selector = Selector.open();ServerSocketChannel ssc = ServerSocketChannel.open();ssc.configureBlocking(false);ServerSocket ss = ssc.socket();ss.bind(new InetSocketAddress(PORT));SelectionKey skey = ssc.register(selector, SelectionKey.OP_ACCEPT);skey.attach(new ServerHandler(ssc, selector));System.out.println("Start ftp server on " + PORT);while(!Thread.interrupted()) {int n = selector.select();if (n == 0) {continue;}Iterator<SelectionKey> it = selector.selectedKeys().iterator();while(it.hasNext()) {SelectionKey key = it.next();it.remove();NioHandler handler = (NioHandler)key.attachment();handler.execute(key);}}} catch (Exception e) {e.printStackTrace();}}public static String ByteBufferToString(ByteBuffer dst) {String ret = null;if (dst != null) {dst.flip();byte[] tempb = new byte[dst.limit()];dst.get(tempb);ret = new String(tempb);}return ret;}public static ByteBuffer StringToByteBuffer(String s) {ByteBuffer other = null;if (s != null) {other = ByteBuffer.wrap(s.getBytes());}return other;}public static int AnalyCmd(String cmd) {int ret = -1;if (cmd.toLowerCase().startsWith("upload")) {ret = 0;} else if (cmd.toLowerCase().startsWith("download")) {ret = 1;} else if (cmd.toLowerCase().equals("ls")) {ret = 2;}return ret;}}

package com.myftpnio.handler;import java.nio.channels.SelectionKey;public interface NioHandler {void execute(SelectionKey key);}

package com.myftpnio.handler;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import com.myftpnio.server.FtpNioServer;public class ServerHandler implements NioHandler {private ServerSocketChannel ssc;private Selector selector;public ServerHandler(ServerSocketChannel ssc, Selector selector) {this.ssc = ssc;this.selector = selector;}@Overridepublic void execute(SelectionKey key) {// TODO Auto-generated method stubtry {String cmd = null;SocketChannel sc = ssc.accept();//读取客户端的命令,并且给客户端回应消息ByteBuffer dst = ByteBuffer.allocate(1024);int ret = sc.read(dst);if (ret > 0) {cmd = FtpNioServer.ByteBufferToString(dst);int n = FtpNioServer.AnalyCmd(cmd);if (n != -1) {String s = "ack";ByteBuffer b = ByteBuffer.wrap(s.getBytes());sc.write(b);} else {String s = "cmd is invalid, please check and try again!!!";ByteBuffer b = ByteBuffer.wrap(s.getBytes());sc.write(b);sc.close();return;}} else {System.out.println("client no send cmd!!!");sc.close();return;}//配置客户端Socket为非阻塞sc.configureBlocking(false);//new 一个新的客户端对象ClientHandler h = new ClientHandler(sc, selector);h.InitClientHandler(cmd);} catch (Exception e) {e.printStackTrace();}}}

package com.myftpnio.handler;import java.io.File;import java.io.IOException;import java.io.RandomAccessFile;import java.nio.ByteBuffer;import java.nio.channels.FileChannel;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.SocketChannel;import com.myftpnio.server.FtpNioServer;public class ClientHandler implements NioHandler {private String cmd;private Selector selector;private SocketChannel sc = null;private FileChannel fileChannel = null;private ByteBuffer buf = ByteBuffer.allocate(1024);private long sum = 0;public ClientHandler(SocketChannel sc, Selector selector) {this.sc = sc;this.selector = selector;FtpNioServer.connum++;System.out.println(FtpNioServer.connum + " Client:" + sc.socket().getRemoteSocketAddress().toString() + " open");}public int InitClientHandler(String cmd) {// 参数判空if (cmd == null) {return 1;}this.cmd = cmd;try {SelectionKey key = null;int n = FtpNioServer.AnalyCmd(this.cmd);if (n == 0) {key = this.sc.register(this.selector, SelectionKey.OP_READ);key.attach(this);} else {key = this.sc.register(this.selector, SelectionKey.OP_WRITE);key.attach(this);}} catch (Exception e) {e.printStackTrace();return 1;}return 0;}@Overridepublic void execute(SelectionKey key) {if (key.isReadable()) {try {int n = FtpNioServer.AnalyCmd(this.cmd);switch(n) {case 0:proccessUpLoadCmd(key);break;}} catch (Exception e) {e.printStackTrace();return;}return;}if (key.isWritable()) {try {int n = FtpNioServer.AnalyCmd(this.cmd);switch(n) {case 1:proccessDownLoadCmd(key);break;case 2:proccessLsCmd(key);break;}} catch (Exception e) {e.printStackTrace();return;}return;}}private void proccessUpLoadCmd(SelectionKey key) {String s[] = this.cmd.split(":");String filepath = FtpNioServer.ROOT + s[1];try {int n = sc.read(buf);if (n >= 0) {sum += n;WriteToFile(filepath, buf);} else {ReleaseResource(key);System.out.println(FtpNioServer.connum + " read sum:" + sum + " Client:" + sc.socket().getRemoteSocketAddress().toString() + " close");FtpNioServer.connum--;return;}} catch (IOException e) {try {ReleaseResource(key);FtpNioServer.connum--;} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}System.out.println("IOException " + FtpNioServer.connum + " Client:" + sc.socket().getRemoteSocketAddress().toString() + " close");return;}}private void proccessDownLoadCmd(SelectionKey key) {String s[] = this.cmd.split(":");String filepath = FtpNioServer.ROOT + s[1];try {int n = ReadFromFile(filepath, buf);if (n >= 0) {sum += n;buf.flip();sc.write(buf);} else {ReleaseResource(key);System.out.println(FtpNioServer.connum + " send sum:" + sum + " Client:" + sc.socket().getRemoteSocketAddress().toString() + " close");FtpNioServer.connum--;return;}} catch (Exception e) {try {ReleaseResource(key);FtpNioServer.connum--;} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}System.out.println("IOException " + FtpNioServer.connum + " Client:" + sc.socket().getRemoteSocketAddress().toString() + " close");return;}}private void proccessLsCmd(SelectionKey key) throws IOException {File dir = new File(FtpNioServer.ROOT);File files[] = dir.listFiles();String ret = null;for (File f : files) {if (ret == null) {ret = f.getName();} else {ret += ";";ret += f.getName();}}ByteBuffer src = null;if (ret != null) {src = ByteBuffer.wrap(ret.getBytes());} else {String error = "cmd execute fail!!!";src = ByteBuffer.wrap(error.getBytes());}// write data to client socket channelthis.sc.write(src);ReleaseResource(key);System.out.println(FtpNioServer.connum + " Client:" + sc.socket().getRemoteSocketAddress().toString() + " close");FtpNioServer.connum--;}private void WriteToFile(String path, ByteBuffer buf) throws IOException {if (fileChannel == null) {fileChannel = new RandomAccessFile(path, "rw").getChannel();}buf.flip();fileChannel.write(buf);buf.clear();}@SuppressWarnings("resource")private int ReadFromFile(String path, ByteBuffer buf) throws IOException {if (fileChannel == null) {fileChannel = new RandomAccessFile(path, "r").getChannel();}buf.clear();return fileChannel.read(buf);}private void ReleaseResource(SelectionKey key) throws IOException {sc.close();key.cancel();if (fileChannel != null) {fileChannel.close();}}}






原创粉丝点击