網絡編程_多線程的文件上傳小示例
https://blog.csdn.net/zsw101259/article/details/7768908
1、多線程文件的上傳,數據流向
1)、客戶端Socket:
①out File對象
②out 文件內容
③in 服務端反饋信息
2)、服務端的處理
①每接收一個Socket,創建一個線程去處理這個Socket
②in File對象:判斷文件的類型、選擇不同的傳輸方式、創建File對象關聯文件
③in 文件內容:填充File對象關聯文件內容
④填充完File文件,給客戶端反饋
2、代碼:
1)客戶端:字符流
- import java.net.*;
- import java.io.*;
- /**
- * @author Administrator @zsw 2012-7-18 上午09:21:04
- *
- * 需求:從客戶端上傳文本文件到服務端
- *
- * 客戶端上傳:
- * ①定義Socket、文件輸入流、Socket輸出流、Socket輸入流
- * ②從文件輸入讀取文件,
- * 添加:首先上傳文件File對象和文件類型int filetype
- * ③將讀到的數據寫入Socket輸出流中
- * ④關閉資源
- */
- public class TextUploadClient2 {
- public static void main(String[] args) throws Exception{
- File file=new File("D:\\1.txt");
- //①:定義資源
- Socket s=new Socket("127.0.0.1",10007);
- BufferedReader bufr=new BufferedReader(new FileReader(file));
- //字符流轉換成字節流
- BufferedWriter bufout=new BufferedWriter(
- new OutputStreamWriter(s.getOutputStream()));
- // PrintWriter out=new PrintWriter(s.getOutputStream(),true);
- BufferedReader bufin=new BufferedReader(
- new InputStreamReader(s.getInputStream()));
- //將文件對象傳到服務器
- ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
- oos.writeObject(file);
- //②上傳數據
- String line=null;
- while((line=bufr.readLine())!=null){
- // System.out.println(line);
- bufout.write(line);
- bufout.newLine();
- bufout.flush();
- }
- //③告訴服務器,客戶端已經傳完了。並接收服務端的反饋信息
- s.shutdownOutput();//關閉客戶端的輸出流,相當於在流中寫-1
- String line2=null;
- while((line2=bufin.readLine())!=null){
- if("success".equals(line2)){
- System.out.println("上傳文件成功!");
- break;
- }
- }
- //④關閉資源
- bufr.close();
- s.close();
- }
- }
2)客戶端:字符流
- import java.io.*;
- import java.net.*;
- /**
- * @author Administrator @zsw 2012-7-18 下午06:45:41
- *客戶端:
- *①服務端點:Socket、流
- *②讀取客戶端的圖片數據
- *③通過Socket輸出流將數據發給服務端
- *④讀取服務端反饋信息
- *⑤關閉資源
- */
- public class UploadPicClient2 {
- public static void main(String[] args) throws Exception{
- File file=new File("D:\\1.mp3");
- //①服務端點:
- Socket s=new Socket("127.0.0.1",10007);
- FileInputStream fis=new FileInputStream(file);
- OutputStream out=s.getOutputStream();
- InputStream in=s.getInputStream();
- //將文件對象傳到服務器
- ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
- oos.writeObject(file);
- //②讀取圖片
- byte[]buf=new byte[1024*2];
- int len=0;
- while((len=fis.read(buf))!=-1){
- //③發送數據到服務端
- out.write(buf, 0, len);
- }
- //給服務端發送結束標記
- s.shutdownOutput();
- //④讀取服務端反饋信息
- len=0;
- while((len=in.read(buf))!=-1){
- String str=new String(buf,0,len);
- System.out.println("服務端反饋:"+str);
- }
- //⑤關閉資源
- fis.close();
- s.close();
- }
- }
3)服務端:使用多線程
- import java.io.*;
- import java.net.*;
- /**
- * 總結:多線程文件的上傳,數據流向
- * 1、客戶端Socket:①out File對象 ②out 文件內容 ③in 服務端反饋信息
- *
- * 3、服務端的處理
- * ①每接收一個Socket,創建一個線程去處理這個Socket
- * ②in File對象:判斷文件的類型、選擇不同的傳輸方式、創建File對象關聯文件
- * ③in 文件內容:填充File對象關聯文件內容
- * ④填充完File文件,給客戶端反饋
- *
- *
- * @author Administrator @zsw 2012-7-18 下午07:03:47
- * 此類在UploadPicServer.java上麵做改進,使用了多線程.
- *
- *1單線程服務端:有局限,當A客戶連接上來後,<br>
- *被服務器接收後, 服務端執行具體流程中,這時,B客戶端連接,隻有等待。
- *因為服務端還沒有處理完A客戶端的請求,
- *還沒有循環回來執行下次 accept方法,所以暫時獲取不到B客戶端對象
- *
- *2解決思路:那麼為了可以讓多個客戶端同時並發的訪問服務器,
- *服務端最好就是將每一個客戶端封裝到一個單獨的線程中。
- *
- *
- *
- */
- /*
- * 如何定義線程呢: 明確每一個客戶端要在服務端執行的代碼,將該代碼放入run方法中
- */
- //3、線程類
- class UploadThread implements Runnable {
- // 客戶端、文件、文件類型(簡單點0表示文本、1表示字節流)
- private Socket s;
- UploadThread(Socket s) {
- this.s = s;
- }
- public void run() {
- try {
- Thread.sleep(5000);
- new FileUpload().upload(s);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- // 1、主程序
- public class UploadPicByThread {
- public static void main(String[] args) throws Exception {
- // ①定義服務端點:
- ServerSocket ss = new ServerSocket(10007);
- //②為每一個客戶端開啟一個
- int cNum=0;
- while (true) {
- Socket s = ss.accept();
- cNum++;
- new Thread(new UploadThread(s)).start();
- System.out.println("上傳成功文件數:"+cNum);
- }
- }
- }
4、服務端:業務類,根據不同的上傳,選擇不同的方式
- import java.io.*;
- import java.net.*;
- // 2、業務類
- public class FileUpload {
- public void upload(Socket s) {
- try {
- ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
- File file=(File)ois.readObject();
- //當發現文件存在時,修改文件名:如 1.mp3->(count++)1.mp3
- String name=file.getName();//原始文件名
- File dir=new File("D:\\tx\\");
- file=new File(dir,name);
- int count=0;
- while(file.exists()){
- count++;
- file=new File(dir,"("+count+")"+name);
- }
- /*當時文本文件時,調用文本上傳方法
- * 否則調用字符流上傳方法
- */
- if(name.endsWith(".txt")){
- textUpload(s,file);
- }else{
- picUpload(s,file);
- }
- } catch (Exception e) {
- System.out.println(e);
- System.out.println("上傳失敗");
- }
- }
- // ①圖片等多媒體文件上傳(字節流)
- public void picUpload(Socket s, File file) throws Exception{
- //打印客戶端
- String ip=s.getInetAddress().getHostAddress();
- System.out.println(ip+"....connect 準備上傳"+file.getName());
- FileOutputStream fos = new FileOutputStream(file);
- InputStream in = s.getInputStream();
- OutputStream out = s.getOutputStream();
- // ②讀取數據
- int len = 0;
- byte[] buf = new byte[1024 * 2];
- while ((len = in.read(buf)) != -1) {
- fos.write(buf, 0, len);
- }
- // ③給客戶端反饋
- System.out.println(file.getName()+"服務端接收完成");
- out.write("success".getBytes());
- // 給客戶端發送結束標記
- s.shutdownOutput();
- // ④關閉資源
- fos.close();
- s.close();
- }
- // ②文本上傳(字符流)
- public void textUpload(Socket s, File file) throws Exception {
- //打印客戶端連接的
- String ip=s.getInetAddress().getHostAddress();
- System.out.println(ip+"....connect 準備上傳"+file.getName());
- BufferedWriter bufw = new BufferedWriter(new FileWriter(file));
- // Socket 輸出輸入
- BufferedReader bufin = new BufferedReader(new InputStreamReader(
- s.getInputStream()));
- BufferedWriter bufout = new BufferedWriter(new OutputStreamWriter(
- s.getOutputStream()));
- // ②:讀數據、寫到文件、判斷結束、反饋成功
- String line = null;
- /*
- * 服務端收不到line=null的情況,必須在流中添加結束標記 s.shutdownOutput();
- * 關閉客戶端的輸出流,相當於在流中寫-1,line就可以=null
- */
- // 獲取標記符(即時間值)
- while ((line = bufin.readLine()) != null) {
- bufw.write(line);
- bufw.newLine();
- bufw.flush();
- }
- System.out.println(file.getName()+"數據接收成功!");
- bufout.write("success");
- bufout.newLine();
- bufout.flush();
- s.shutdownOutput();
- // 關閉資源
- bufw.close();
- s.close();
- }
- }
最後更新:2017-04-04 07:04:13