java簡単なファイルをアップロードしてサーバーモデル(IO+マルチスレッド)をダウンロードします。

10798 ワード

最近はネットワークプログラミング、マルチスレッド、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;
	}
	
	@Override
	public void execute(SelectionKey key) {
		// TODO Auto-generated method stub
		
		try {
			// get client socket channel
			SocketChannel lsockChannel = null;
			lsockChannel = ssc.accept();
			
			// read data from client socket channel
			ByteBuffer dst = ByteBuffer.allocate(1024);
			lsockChannel.read(dst);
			String cmd = FtpServer.ByteBufferToString(dst);
			
			// set the connect number
			FtpServer.connum.set(FtpServer.connum.get() + 1);
			
			// print the client info
			System.out.println(FtpServer.connum.get() + " client:" + lsockChannel.socket().getRemoteSocketAddress().toString() + " cmd:" + cmd);
			
			// deal Command
			try {
				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 command
		ByteBuffer other = FtpServer.StringToByteBuffer("cmd not exist, please check you command and try again!!!");		
		lsockChannel.write(other);
		
		//close SocketChannel
		lsockChannel.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 channel
		lsockChannel.write(src);
		
		//close SocketChannel
		lsockChannel.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;
	}
	
	@Override
	public 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 channel
						lsockChannel.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 resource
					bis.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;
	}
	
	@Override
	public 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 file
						dst.flip();
						byte[] tempb = new byte[dst.limit()];
						dst.get(tempb);
						bos.write(tempb);	
						dst.clear();
					}
					
					// release resource
					bos.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
", 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
", buf); } else { perror("connect socket fail"); exit(1); } return 0; } void processDownLoad(char *filename, int sock) { printf("processDownLoad
"); 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
"); 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); }