1. 程式人生 > >用Java實現簡單的檔案上傳伺服器和客戶端

用Java實現簡單的檔案上傳伺服器和客戶端

/**
 * 使用TCP協議實現上傳功能的伺服器端
 * 思路:
 * 新建ServerSocket
 * 等待客戶端連線
 * 連線上後開啟子執行緒,把連接獲取的Socket傳給子執行緒
 * 迴圈進行
 * @author yajun
 *
 */
public class UploadServer {
	
	public static void main(String[] args) {
		UploadServer server=new UploadServer();
		UploadThread command=new UploadThread();
		server.start(command);
	}
	
	/**
	 * 功能:接受連線,開啟子執行緒,迴圈
	 * @param command 用於下載的子執行緒物件,該物件實現了Runnable介面
	 */
	private void start(UploadThread command){
		//區域性變數
		ServerSocket serverSocket = null;
		Socket transSocket;
		//業務邏輯
		try {
			serverSocket=new ServerSocket(55555);
			while(true){
				System.out.println("等待連線……");
				transSocket=serverSocket.accept();
				int i=0;
				i++;
				System.out.println("第"+i+"個連線");
				//用不用在下載完後關閉執行緒呢???
				command.setSocket(transSocket);
				Executors.newFixedThreadPool(5).execute(command);
			}
		//異常捕獲
		} catch (IOException e) {
			e.printStackTrace();
		//關閉資源
		} finally{
			try {
				serverSocket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}//End of try
	}//End of connect
	@Test
	public void testConnect() {
		//測試任務:先執行伺服器端,然後多次執行客戶端,伺服器段可以不斷建立子執行緒,則測試成功
		//測試準備:構造一個執行緒,用於模擬下載執行緒
		UploadThread command=new UploadThread();
		start(command);
		
	}

	@Test
	public void testDown() throws IOException {
		byte[] buf;
		ByteArrayInputStream bis;
		String str="canglaoshi.avi\ncontent,content,content";
		buf=str.getBytes();
		bis=new ByteArrayInputStream(buf);
		UploadThread ut=new UploadThread();
		ut.down(bis);
	}
}
//完成各個傳輸任務的子執行緒
class UploadThread implements Runnable{
	
	Socket socket;
	public UploadThread(){}
	public UploadThread(Socket socket){
		this.socket=socket;
	}
	@Override
	public void run() {
		InputStream in;
		try {
			
			in = socket.getInputStream();
			down(in);
			
		//異常處理
		} catch (IOException e) {
			e.printStackTrace();
		} finally{
			try {
				socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		//測試程式碼
		/*try {
			Thread.sleep(5000);
			System.out.println(Thread.currentThread().getName()+",複製完畢");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}*/
	}//End of run
	public void setSocket(Socket socket){
		this.socket=socket;
	}
	//下載方法
	/**
	 * 目標:把InputStream中的資料寫入到本地
	 * 思路:
	 * 1.獲取輸入流,最好傳入輸入流,而不是直接從Socket獲取,傳入有利用單元測試
	 * 2.從輸入流中讀到檔名
	 * 3.新建檔案和檔案輸出流
	 * 4.從輸入流中讀到檔案內容到檔案輸出流
	 * 5.
	 * @throws IOException 
	 */
	public void down(InputStream in) throws IOException{
		//區域性變數
		char ch;
		char[] nameArr=new char[256];
		byte[] buf=new byte[1024];
		String name="";
		OutputStream out = null;
		//業務邏輯
		try {
			//第一步:獲取檔名,構造檔案輸出流
			int i=0;
			while((ch=(char) in.read())!='\n'){
				nameArr[i++]= ch;
			}
			//name=nameArr.toString();//這句話無法將字元陣列轉換為字串,需用下面的語句
			name=new String(nameArr);
			System.out.println("要下載的檔案為:"+name);
			out=new FileOutputStream("src\\down\\"+name);
			//第二步:將輸入流中的其他內容寫入到檔案
			int len;
			while((len=in.read(buf))!=-1){
				out.write(buf,0,len);
			}
			out.flush();
		//異常捕獲
		} catch (IOException e) {
			e.printStackTrace();
		//關閉資源
		}finally{
			//疑問:兩個捕獲可不可以放到一塊呢,怎樣處理關閉流時的異常最好呢?
			in.close();
			out.close();
		}
		//除錯
		System.out.println(name);
	}
	
}//End of UploadThread

檔案上傳客戶端: