2013-09-26 32 views
2

如何在Java套接字編程中實現從客戶端到服務器的持續交互。在我的程序中,我有一個目錄中的許多文件夾ie)F://讀取並且我將文件從客戶端傳輸到服務器。當第一次請求時,一個文件夾從客戶端傳輸到服務器,當它再次到客戶端發送另一個文件夾時,它會一直說異常,java.net.SocketException:在ClientProgram的write()方法中關閉Socket我打電話給socket.getOutputStream()。所以請告訴我如何解決這個問題。我想我想爲每次傳輸使用線程,所以請告訴我必須在哪裏運行這個罰款。十分感謝。如何在Java套接字編程中實現從客戶端到服務器的持續交互

客戶端代碼:

在每個時間向前方法和寫方法傳遞數據的從客戶端到服務器。和listf(String directoryName)方法遞歸地運行文件和文件夾,當它發現文件夾時它調用的forward()和write()方法。 forward()用於傳遞特定文件夾的目錄路徑,write()方法用於在客戶端寫入所有文件,並且每次都通過listf(String directoryName)傳遞給服務器。在第一次這種方法運行良好。當第二次再次調用write()方法時,在那裏給出java.net.SocketException:Socket被關閉,爲什麼它發生。

import java.io.*; 
import java.net.*; 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.List; 
import java.util.ListIterator; 
import java.io.IOException; 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

public class ClientProgram extends HttpServlet { 

    private static final long serialVersionUID = 1L; 

    public ClientProgram() { 
     super(); 
    } 
    Socket socket; 
    ClientProgram clientProgram; 
    String hostDomain = "192.168.1.19"; 
    int port = 5855; 
    BufferedOutputStream bos; 
    DataOutputStream dos; 
    BufferedInputStream bis; 
    FileInputStream fis; 
    PrintStream pr; 
    BufferedReader gt; 
    List<File> resultList; 

    public static listf(String directoryName) throws IOException { 
     try { 
      File directory = new File(directoryName); 
      resultList = new ArrayList<File>(); 
      // get all the files from a directory 
      File[] fList = directory.listFiles(); 
      resultList.addAll(Arrays.asList(fList)); 
      for (File file : fList) { 
       if (file.isFile()) { 
        System.out.println("file: " + file.getAbsolutePath()); 
       } else if (file.isDirectory()) { 
        String pathtomake = file.getAbsolutePath(); 
        System.out.println("folder now: " + pathtomake); 
        forward(pathtomake); 
        write(pathtomake); 
        System.out.println("folder: " + file.getAbsolutePath()); 
        listf(file.getAbsolutePath()); 

       } 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } finally { 
      if (bis != null) { 
       bis.close(); 
      } 
      if (dos != null) { 
       dos.close(); 
      } 
      if (fis != null) { 
       fis.close(); 
      } 
     } 
     return resultList; 
    } 

    public void write(String rec) throws IOException { 
     try { 
      System.out.println("rr"); 
      bos = new BufferedOutputStream(socket.getOutputStream()); 
      dos = new DataOutputStream(bos); 
      File file1 = new File(rec); 
      File[] fil_Files_list = file1.listFiles(); 
      dos.writeInt(fil_Files_list.length); 
      System.out.println("file will .."); 
      for (File file : fil_Files_list) { 
       long length = file.length(); 
       dos.writeLong(length); 
       String name = file.getName(); 
       dos.writeUTF(name); 
       fis = new FileInputStream(file); 
       bis = new BufferedInputStream(fis); 
       System.out.println("writin.."); 
       int theByte = 0; 
       while ((theByte = bis.read()) != -1) { 
        bos.write(theByte); 
       } 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } finally { 
     } 
    } 

    public void forward(String drc) throws UnknownHostException, IOException { 
     boolean b = socket.isConnected(); 
     System.out.println("Socket Is active or not: " + b); 
     pr = new PrintStream(socket.getOutputStream()); 
     pr.println(drc); 
     gt = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
     String tm = gt.readLine(); 
     System.out.print(tm); 
    } 

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     socket = new Socket(hostDomain, port); 
     String directory = "F://read"; 
     listf(directory); 

    } 

} 

服務器代碼:

這是我的服務器代碼接受與文件夾接收。在這裏我正在接收文件夾路徑使用客戶端方法稱爲forward()並添加到detination路徑即緩衝區讀取器)d://保存。之後,我將所有文件寫入客戶端方法write()中的特定文件夾。

import java.io.*; 
import java.net.*; 
import java.io.IOException; 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

public class ServerProgram extends HttpServlet { 

    private static final long serialVersionUID = 1L; 

    public ServerProgram() { 
     super(); 
     // TODO Auto-generated constructor stub 
    } 

    BufferedReader ed; 
    PrintStream pr; 
    BufferedInputStream bis; 
    DataInputStream dis; 
    FileOutputStream fos; 
    BufferedOutputStream bos; 
    Socket socket; 

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     try { 
      System.out.println(1); 
      ServerSocket serverSocket = new ServerSocket(5792); 
      System.out.println(2); 
      socket = serverSocket.accept(); 

      ed = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
      String tmp = ed.readLine(); 
      System.out.print("I Recieved :" + tmp); 
      pr = new PrintStream(socket.getOutputStream()); 
      String str = "Yup I got it !!"; 
      pr.println(str); 
      int g = tmp.indexOf("\\"); 
      String di = tmp.substring(g); 
      String dirPath = "D://save//" + di; 
      System.out.println(dirPath); 
      File file = new File(dirPath); 
      JavaHeapMemory(); 

      if (file.exists() || file.mkdirs()) { 
       bis = new BufferedInputStream(socket.getInputStream()); 
       dis = new DataInputStream(bis); 
       int filesCount = dis.readInt(); 
       File[] files = new File[filesCount]; 
       for (int i = 0; i < filesCount; i++) { 
        long fileLength = dis.readLong(); 
        String fileName = dis.readUTF(); 
        System.out.println("name of the file: " + fileName); 
        files[i] = new File(dirPath + "/" + fileName); 
        FileOutputStream fos = new FileOutputStream(files[i]); 
        BufferedOutputStream bos = new BufferedOutputStream(fos); 
        for (int j = 0; j < fileLength; j++) { 
         bos.write(bis.read()); 
        } 

       } 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } finally { 
      if (bos != null) { 
       bos.close(); 
      } 
      if (dis != null) { 
       dis.close(); 
      } 
      try { 
       socket.close(); 
      } catch (Exception e) { 
       // TODO: handle exception 
      } 
     } 
    } 

    public void JavaHeapMemory() { 
     long heapSize = Runtime.getRuntime().totalMemory(); 
     System.out.println("Heap Size = " + heapSize); 
    } 
} 

例外:

  java.net.SocketException: Socket is closed 
       at java.net.Socket.getOutputStream(Unknown Source) 
       at pack.ClientProgram.forward() 

在我用於文件夾遞歸傳輸到服務器此以上客戶端程序。但它不是從客戶端連續運行到服務器,所以請告訴我這樣做的方法。我非常感謝。

回答

2

您可以混合文本和二進制文件,而不會產生混淆。

ed = new BufferedReader(new InputStreamReader(socket.getInputStream())); 

這意味着BufferedReader可以讀取儘可能多的數據,而不僅僅是要求多少。

bis = new BufferedInputStream(socket.getInputStream()); 

這將開始在一些隨機點讀取二進制的BufferedReader中沒有讀(不是你要的量)

總之,只有使用二進制或文本流,除非你真的知道你在做什麼。


你的程序有

while ((theByte = bis.read()) != -1) 
     bos.write(theByte); 

這意味着,一直讀到流的末尾。這也意味着它將讀取連接關閉前發送的所有數據。

如果您想在同一個流中發送多個文件,則需要另一種方式讓接收方知道文件何時結束。最簡單的方法是首先發送文件大小,並讓接收者只讀取那麼多數據。

BTW一次讀取一個字節是非常慢很慢。我建議你讀入大小爲4KB的字節[]。

相關問題