java 简单的文件上传下载服务器模型(IO + 多线程)

来源:互联网 发布:绿色傲剑金蛇剑法数据 编辑:程序博客网 时间:2024/05/16 05:28

最近学习网络编程,多线程,IO等知识,综合这些知识写了个简单的文件上传下载服务器模型,目前是基于IO+多线程的方式,比较简单,异常基本没有处理,将就一下,哈

哈。后续会将其改造为NIO的方式,最后再将其改造成NIO+多线程的方式,敬请期待,^_^

服务器端基于Java IO+多线程

package com.myftp.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 java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.atomic.AtomicInteger;import com.myftp.handler.FtpHandler;import com.myftp.handler.FtpServerHandler;public class FtpServer {public final static int PORT = 5000;public final static String ROOT = "D:/FtpDir/";public static AtomicInteger connum = new AtomicInteger(0);public static ExecutorService exc = Executors.newCachedThreadPool();public static void main(String argv[]) {try {Selector s = Selector.open();ServerSocketChannel ssc = ServerSocketChannel.open();ssc.configureBlocking(false);SelectionKey key = ssc.register(s, SelectionKey.OP_ACCEPT);key.attach(new FtpServerHandler(s, ssc));ServerSocket ss = ssc.socket();ss.bind(new InetSocketAddress(PORT));System.out.println("Start ftp server on " + PORT);while (!Thread.interrupted()) {int n = s.select();if (n == 0) {continue;        }Iterator<SelectionKey> it = s.selectedKeys().iterator();            while (it.hasNext())             {                SelectionKey sk = it.next();                it.remove();                                FtpHandler handler = (FtpHandler) sk.attachment();handler.execute(sk);            }}} 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;}}

package com.myftp.handler;import java.io.File;import java.io.IOException;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.myftp.downloadthread.DownLoadFile;import com.myftp.server.FtpServer;import com.myftp.uploadthread.UpLoadFile;public class FtpServerHandler implements FtpHandler {private ServerSocketChannel ssc;public FtpServerHandler(Selector selector, ServerSocketChannel ssc) {this.ssc = ssc;}@Overridepublic void execute(SelectionKey key) {// TODO Auto-generated method stubtry {// get client socket channelSocketChannel lsockChannel = null;lsockChannel = ssc.accept();// read data from client socket channelByteBuffer dst = ByteBuffer.allocate(1024);lsockChannel.read(dst);String cmd = FtpServer.ByteBufferToString(dst);// set the connect numberFtpServer.connum.set(FtpServer.connum.get() + 1);// print the client infoSystem.out.println(FtpServer.connum.get() + " client:" + lsockChannel.socket().getRemoteSocketAddress().toString() + " cmd:" + cmd);// deal Commandtry {processCmd(cmd, lsockChannel);} catch (Exception e) {e.printStackTrace();}} catch (Exception e) {e.printStackTrace();}}public void processCmd(String cmd, SocketChannel lsockChannel) throws IOException {if (cmd.toLowerCase().equals("ls")) {lsCmd(cmd, lsockChannel);return;}if (cmd.toLowerCase().startsWith("download")) {downloadCmd(cmd, lsockChannel);return;}if (cmd.toLowerCase().startsWith("upload")) {uploadCmd(cmd, lsockChannel);return;}// send client with data:no match commandByteBuffer other = FtpServer.StringToByteBuffer("cmd not exist, please check you command and try again!!!");lsockChannel.write(other);//close SocketChannellsockChannel.close();}public void lsCmd(String cmd, SocketChannel lsockChannel) throws IOException {File dir = new File(FtpServer.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 channellsockChannel.write(src);//close SocketChannellsockChannel.close();}public void downloadCmd(String cmd, SocketChannel lsockChannel) throws IOException {String f[] = cmd.split(":");String filepath = FtpServer.ROOT + f[1];Runnable r = new DownLoadFile(filepath, lsockChannel);FtpServer.exc.execute(r);return;}public void uploadCmd(String cmd, SocketChannel lsockChannel) throws IOException {String f[] = cmd.split(":");String tmp[] = f[1].split("/");String filepath = FtpServer.ROOT + tmp[tmp.length -1];Runnable r = new UpLoadFile(filepath, lsockChannel);FtpServer.exc.execute(r);return;}}
package com.myftp.downloadthread;import java.io.BufferedInputStream;import java.io.FileInputStream;import java.nio.ByteBuffer;import java.nio.channels.SocketChannel;import java.util.Arrays;public class DownLoadFile implements Runnable {private String filepath;private SocketChannel lsockChannel;public DownLoadFile(String filepath, SocketChannel lsockChannel) {this.filepath = filepath;this.lsockChannel = lsockChannel;}@Overridepublic void run() {try {FileInputStream fis = null;BufferedInputStream bis = null;fis = new FileInputStream(filepath);if (fis != null) {bis = new BufferedInputStream(fis);if (bis != null) {byte[] bs = new byte[512];while(bis.available() > 512) {bis.read(bs);ByteBuffer src = ByteBuffer.wrap(bs);// write data to client socket channellsockChannel.write(src);Arrays.fill(bs, (byte)0);}// 处理不足512的剩余部分int remain = bis.available(); byte[] last = new byte[remain];bis.read(last);lsockChannel.write(ByteBuffer.wrap(last));             // release resourcebis.close();fis.close();lsockChannel.close();} }} catch (Exception e) {e.printStackTrace();}}}

package com.myftp.uploadthread;import java.io.BufferedOutputStream;import java.io.FileOutputStream;import java.nio.ByteBuffer;import java.nio.channels.SocketChannel;public class UpLoadFile implements Runnable {private String path;private SocketChannel sc;public UpLoadFile(String path, SocketChannel sc) {this.path = path;this.sc = sc;}@Overridepublic void run() {try {FileOutputStream fos = null;BufferedOutputStream bos = null;fos = new FileOutputStream(path);if (fos != null) {bos = new BufferedOutputStream(fos);if (bos != null) {ByteBuffer dst = ByteBuffer.allocate(512);while(true) {int n = sc.read(dst);if (n == 0) {continue;}if (n == -1) {break;}// write to filedst.flip();byte[] tempb = new byte[dst.limit()];dst.get(tempb);bos.write(tempb);dst.clear();}// release resourcebos.close();fos.close();sc.close();}}} catch (Exception e) {e.printStackTrace();}}}

客户端基于C语言,阻塞方式。

#include <netinet/in.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>void processDownLoad(char* filename, int sock);void processUpLoad(char* path, int sock);char* path = "/home/ftpclient/";int main(int argc, char** argv) {if (argc != 4) {printf("Usage: %s server_ip server_port content\n", argv[0]);exit(1);}int ret = -1;int sock = -1;char buf[1024] = {0};struct sockaddr_in ftpserver;sock = socket(PF_INET, SOCK_STREAM, 0);if (sock == -1){perror("create socket fail");exit(1);}memset(&ftpserver, 0 ,sizeof(ftpserver));ftpserver.sin_family = AF_INET;ftpserver.sin_addr.s_addr = inet_addr(argv[1]);ftpserver.sin_port = htons(atoi(argv[2]));ret = connect(sock, (struct sockaddr*)&ftpserver, sizeof(ftpserver));if (ret != -1) {send(sock, argv[3], strlen(argv[3]), 0);char *down = NULL;down = strstr(argv[3], "download");if (down != NULL){char filename[128] = {0};char *p = strstr(argv[3], ":");strcpy(filename, p+1);processDownLoad(filename, sock);return 0;}char *up = NULL;up = strstr(argv[3], "upload");if (up != NULL){char path[128] = {0};char *p = strstr(argv[3], ":");strcpy(path, p+1);processUpLoad(path, sock);return 0;}recv(sock, buf, 1024, 0);close(sock);printf("%s\n", buf);}else {perror("connect socket fail");exit(1);}return 0;}void processDownLoad(char *filename, int sock){printf("processDownLoad\n");char buf[1024] = {0};char name[128] = {0};strcat(name, path);strcat(name, filename);FILE* f = fopen(name, "a");if (f != NULL){int recv_len = recv(sock, buf, 1024, 0);while(recv_len > 0){fwrite(buf, recv_len, 1, f);memset(buf, 0, 1024);recv_len = recv(sock, buf, 1024, 0);}}else{perror("open file fail!");close(sock);exit(1);}fclose(f);close(sock);}void processUpLoad(char* path, int sock){printf("processUpLoad\n");char buf[1024] = {0};FILE* f = fopen(path, "r+");if (f != NULL) {int read_len = fread(buf, 1, 1024, f);while( read_len  >= 0){send(sock, buf, read_len, 0);if (feof(f)){break;}memset(buf, 0, 1024);read_len = fread(buf, 1, 1024, f);}}else{perror("open file fail!");close(sock);exit(1);}close(f);close(sock);}