生活随笔
收集整理的這篇文章主要介紹了
C/S+P2P网络模型(二)--上传下载文件
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
原文地址:http://blog.csdn.net/whoami021/article/details/21656875
上一篇文章我們實現聊天的功能,下面我們看文件傳輸怎么實現。
我的做法是:增加一個文件服務器,所有上傳和下載文件的操作都由文件服務器來處理。
因此處理邏輯是這樣的:如果用戶請求上傳文件或者下載文件,那么就將用戶直接與文件服務器通信,而不用經過中央服務器。
所以現在的問題是知道java怎么實現上傳和下載文件,如果這個問題解決了,那基本就搞定了。
首先,文件傳輸基本都是用面向連接的方式。因為無連接的方式容易丟包,一旦丟了一個數據包,文件就壞了,所有努力全白費。但是需要注意的是面向連接的方式,在服務器處理完一個連接后該連接就關閉了。
下面看代碼,在原來的基礎上我新建了兩個主要文件:FileServer.java和FileClient..java。
[java] view plaincopy
package?chat.net.file;????import?java.io.BufferedInputStream;??import?java.io.BufferedOutputStream;??import?java.io.DataInputStream;??import?java.io.DataOutputStream;??import?java.io.File;??import?java.io.FileInputStream;??import?java.io.FileOutputStream;??import?java.io.IOException;??import?java.net.ServerSocket;??import?java.net.Socket;??import?java.util.Iterator;??import?java.util.Set;??import?java.util.TreeMap;????import?chat.Globals;???????????public?class?FileServer?{????????private?TreeMap<String,?String>?fileMap?=?new?TreeMap<>();????????private?final?String?SavePath?=?"save/";????????private?final?int?port?=?8821;????????private?ServerSocket?ss;????????private?Socket?s;????????private?String?sender;????????private?String?receiver;????????private?int?bufferSize?=?8192;????????public?void?start()?{??????????try?{????????????????????????????File?file?=?new?File(SavePath);??????????????if?(!file.exists())?{??????????????????file.mkdir();??????????????}??????????????ss?=?new?ServerSocket(port);??????????????while?(true)?{??????????????????s?=?ss.accept();??????????????????DataInputStream?dis?=?new?DataInputStream(??????????????????????????new?BufferedInputStream(s.getInputStream()));??????????????????dis.readByte();??????????????????int?req?=?dis.readInt();??????????????????if?(req?==?Globals.UploadReq)?{??????????????????????recvFile(dis);??????????????????}?else?{??????????????????????sendFile(dis);??????????????????}??????????????}??????????}?catch?(IOException?e)?{????????????????????????????e.printStackTrace();??????????}??????}????????private?void?recvFile(DataInputStream?dis)?{??????????DataOutputStream?dos?=?null;??????????try?{??????????????sender?=?dis.readUTF();??????????????String?savePath?=?SavePath;??????????????byte[]?buf?=?new?byte[bufferSize];??????????????long?len?=?0;????????????????String?fileName?=?dis.readUTF();??????????????if?(fileName.equals(String.valueOf(Globals.Exit)))?{??????????????????dis.close();??????????????????return;??????????????}????????????????savePath?+=?fileName;??????????????dos?=?new?DataOutputStream(new?BufferedOutputStream(??????????????????????new?BufferedOutputStream(new?FileOutputStream(savePath))));??????????????len?=?dis.readLong();????????????????System.out.println("文件的長度為:"?+?len);????????????????while?(true)?{??????????????????int?read?=?0;??????????????????if?(dis?!=?null)?{??????????????????????read?=?dis.read(buf);??????????????????}??????????????????if?(read?==?-1)?{??????????????????????break;??????????????????}??????????????????dos.write(buf,?0,?read);??????????????}??????????????fileMap.put(fileName,?sender);??????????????System.out.println("接收完成,文件存為"?+?savePath);??????????}?catch?(Exception?e)?{??????????????e.printStackTrace();??????????}?finally?{??????????????try?{??????????????????dis.close();??????????????????if?(dos?!=?null)?{??????????????????????dos.close();??????????????????}??????????????}?catch?(IOException?e)?{????????????????????????????????????e.printStackTrace();??????????????}??????????}??????}????????private?void?sendFile(DataInputStream?dis)?{??????????DataOutputStream?dos?=?null;??????????DataInputStream?fis?=?null;??????????try?{??????????????receiver?=?dis.readUTF();??????????????dos?=?new?DataOutputStream(s.getOutputStream());????????????????????????????String?fileList?=?"文件列表:\n";??????????????if?(fileMap.size()?==?0)?{??????????????????dos.writeUTF("");??????????????????return;??????????????}??????????????Set<String>?set?=?fileMap.keySet();??????????????Iterator<String>?it?=?set.iterator();??????????????String?key;??????????????int?i?=?0;??????????????while?(it.hasNext())?{??????????????????++i;??????????????????key?=?it.next();??????????????????fileList?+=?i?+?".<"?+?key?+?","?+?fileMap.get(key)?+?">";??????????????}??????????????dos.writeUTF(fileList);??????????????String?fileName?=?getFileName(fileList,?dis.readInt());??????????????File?file?=?new?File(SavePath?+?fileName);????????????????????????????fis?=?new?DataInputStream(new?BufferedInputStream(??????????????????????new?FileInputStream(file)));??????????????dos.writeUTF(fileName);??????????????dos.flush();??????????????dos.writeLong((long)?file.length());??????????????dos.flush();????????????????byte[]?buf?=?new?byte[bufferSize];??????????????int?read?=?0;????????????????while?(true)?{??????????????????read?=?fis.read(buf);??????????????????if?(read?==?-1)?{??????????????????????break;??????????????????}??????????????????dos.write(buf,?0,?read);??????????????}??????????????dos.flush();??????????????System.out.println("文件"?+?fileName?+?"傳輸完成");??????????}?catch?(Exception?e)?{????????????????????????????e.printStackTrace();??????????}?finally?{??????????????try?{??????????????????dis.close();??????????????????if?(fis?!=?null)?{??????????????????????fis.close();??????????????????}??????????????????dos.close();??????????????}?catch?(IOException?e)?{????????????????????????????????????e.printStackTrace();??????????????}??????????}??????}????????private?String?getFileName(String?fileList,?int?no)?{??????????String?fileName?=?fileList.substring(fileList.indexOf(String??????????????????.valueOf(no)));??????????fileName?=?fileName.substring(fileName.indexOf("<")?+?1,??????????????????fileName.indexOf(","));??????????return?fileName;??????}????????public?static?void?main(String[]?args)?{??????????new?FileServer().start();??????}??}??[java] view plaincopy
package?chat.net.file;????import?java.io.BufferedInputStream;??import?java.io.BufferedOutputStream;??import?java.io.DataInputStream;??import?java.io.DataOutputStream;??import?java.io.File;??import?java.io.FileInputStream;??import?java.io.FileOutputStream;??import?java.io.IOException;??import?java.net.Socket;??import?java.net.UnknownHostException;??import?java.util.Scanner;????import?chat.Globals;???????????public?class?FileClient?{????????private?String?HOST?=?"127.0.0.1";????????private?final?int?port?=?8821;????????private?Socket?socket;????????private?String?ENV?=?"linux";????????private?int?bufferSize?=?8192;????????private?Scanner?sc?=?new?Scanner(System.in);???????????????????public?void?uploadFile(int?req,?String?peer)?{??????????try?{??????????????socket?=?new?Socket(HOST,?port);??????????????sendMessage(req,?peer);??????????????System.out.print("輸入上傳文件的絕對路徑:");??????????????String?path?=?sc.next();????????????????????????????????????????????File?file?=?new?File(path);??????????????DataInputStream?dis?=?new?DataInputStream(new?BufferedInputStream(??????????????????????new?FileInputStream(file)));??????????????DataOutputStream?dos?=?new?DataOutputStream(??????????????????????socket.getOutputStream());??????????????if?(!file.exists())?{??????????????????System.out.println("該文件不存在");??????????????????dos.writeUTF(String.valueOf(Globals.Exit));??????????????????dos.flush();??????????????????return;??????????????}??????????????sendFile(dis,?dos,?file);??????????}?catch?(Exception?e)?{????????????????????????????e.printStackTrace();??????????}??????}????????private?void?sendFile(DataInputStream?dis,?DataOutputStream?dos,?File?file)?{??????????try?{????????????????????????????dos.writeUTF(file.getName());??????????????dos.flush();??????????????dos.writeLong((long)?file.length());??????????????dos.flush();????????????????byte[]?buf?=?new?byte[bufferSize];??????????????int?read?=?0;????????????????while?(true)?{??????????????????read?=?dis.read(buf);??????????????????if?(read?==?-1)?{??????????????????????break;??????????????????}??????????????????dos.write(buf,?0,?read);??????????????}??????????????dos.flush();??????????????????????????????????????????dis.close();??????????????dos.close();??????????}?catch?(Exception?e)?{????????????????????????????e.printStackTrace();??????????}??????}???????????????????public?void?downloadFile(int?req,?String?peer)?{??????????try?{??????????????socket?=?new?Socket(HOST,?port);??????????????sendMessage(req,?peer);??????????????DataInputStream?dis?=?new?DataInputStream(socket.getInputStream());??????????????DataOutputStream?dos?=?new?DataOutputStream(??????????????????????socket.getOutputStream());????????????????????????????String?fileList?=?dis.readUTF();??????????????if?(fileList.equals(""))?{??????????????????System.out.println("服務器沒有文件");??????????????????return;??????????????}??????????????System.out.println(fileList);??????????????System.out.print("輸入要下載的文件序號:");??????????????dos.writeInt(sc.nextInt());??????????????dos.flush();??????????????System.out.print("輸入文件的保存位置(絕對路徑):");??????????????String?savePath?=?sc.next();????????????????????????????recvFile(dis,?dos,?savePath);??????????}?catch?(Exception?e)?{????????????????????????????e.printStackTrace();??????????}??????}????????private?void?sendMessage(int?req,?String?peer)?{??????????DataOutputStream?dos?=?null;??????????try?{??????????????dos?=?new?DataOutputStream(socket.getOutputStream());??????????????if?(ENV.equalsIgnoreCase("windows"))?{??????????????????dos.writeByte(0x1);??????????????????dos.flush();??????????????}?else?if?(ENV.equalsIgnoreCase("unix"))?{??????????????????dos.writeByte(0x2);??????????????????dos.flush();??????????????}?else?if?(ENV.equalsIgnoreCase("linux"))?{??????????????????dos.write(0x3);??????????????????dos.flush();??????????????}?else?{??????????????????dos.writeUTF(ENV);??????????????????dos.flush();??????????????}??????????????dos.writeInt(req);??????????????dos.writeUTF(peer);??????????????dos.flush();??????????}?catch?(Exception?e)?{????????????????????????????e.printStackTrace();??????????}??????}????????private?void?recvFile(DataInputStream?dis,?DataOutputStream?dos,??????????????String?savePath)?{??????????try?{??????????????byte[]?buf?=?new?byte[bufferSize];??????????????long?len?=?0;????????????????String?fileName?=?dis.readUTF();??????????????if?(!savePath.endsWith("/"))?{??????????????????savePath?+=?"/";??????????????}??????????????savePath?+=?fileName;??????????????dos?=?new?DataOutputStream(new?BufferedOutputStream(??????????????????????new?BufferedOutputStream(new?FileOutputStream(savePath))));??????????????len?=?dis.readLong();????????????????System.out.println("文件的長度為:"?+?len);????????????????int?read?=?0;??????????????while?(true)?{??????????????????read?=?dis.read(buf);??????????????????if?(read?==?-1)?{??????????????????????break;??????????????????}??????????????????dos.write(buf,?0,?read);??????????????}??????????????System.out.println("接收完成,文件存為"?+?savePath);??????????????dis.close();??????????????dos.close();??????????}?catch?(Exception?e)?{??????????????e.printStackTrace();??????????}??????}????????public?static?void?main(String[]?args)?{??????????FileClient?client?=?new?FileClient();??????????client.uploadFile(Globals.UploadReq,?"noname");??????????client.downloadFile(Globals.DownloadReq,?"noname");??????}??}??上面這兩個文件就可以實現文件上傳和下載了,有需要完整工程代碼的請點擊這里。
測試的時候先運行兩個服務器:Server和FileServer,然后在運行Main。
總結
以上是生活随笔為你收集整理的C/S+P2P网络模型(二)--上传下载文件的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。