2017-07-18 47 views
-1

[编辑:这篇文章已被标记为重复未经审查正确。这两个帖子解决了完全不同的问题,审阅者没有花时间仔细阅读。]Java TCP文件传输数据随机丢失

服务器将连接到三个客户端实例。服务器有三个线程来接收来自这三个客户端的请求。客户端的三个实例中的每一个都会有一个ServerThread(服务器请求来自该线程的文件或文件列表)和一个UserThread(它将接受用户输入并与服务器通信并根据用户输入接收文件/文件列表) 。

比方说,client_0需要一个拥有client_1的文件。当client_0的UserThread向服务器请求文件时,服务器与client_1的ServerThread进行通信,并且client_1的ServerThread将文件的byteArray发送给服务器。然后,服务器将byteArray发送回到client_0的UserThread和client_0,然后将byteArray保存为文件。

我使用相同类型的服务器代码从client_1接收bytearray,并且client_0从服务器接收byteArray。服务器的代码每次完美工作,完美地接收byteArray,但在client_0中,接收byteArray的循环卡住文件的最后部分,尽管相同类型的循环在服务器中完美工作。变量position保存已收到多少byteArray,并且它不会到达client_0中的FILE_SIZE,但在服务器中没有任何问题。 System.out.println()声明证实了这一点。

此外,client_0中的这个问题发生在90%的时间。在另外的10%中,client_0中的循环就像它应该的那样工作!这是为什么发生?

代码很长,但如果有人设法通过并给出一些建议,这将是一个很大的帮助。

服务器:

package server; 
import java.io.*; 
import java.net.*; 

public class Server { 

    public static void main(String[] args) throws Exception { 
     String[] id={"cp 1","cp 2","cp 3"}, pass={"123","456","789"}; 
     ServerSocket welcome = new ServerSocket(6000), tmpSocket; 
     Socket STsocket, UTsocket; 
     int startSTport = 6001; 
     int startUTport = 6011; 

     // for ServerThread of client 
     BufferedReader STmsgFrom[] = new BufferedReader[3]; 
     PrintWriter STmsgTo[] = new PrintWriter[3]; 
     DataInputStream[] STfileFrom = new DataInputStream[3]; 
     // for UserThread of client 
     BufferedReader UTmsgFrom[] = new BufferedReader[3]; 
     PrintWriter UTmsgTo[] = new PrintWriter[3]; 
     DataOutputStream[] UTfileTo = new DataOutputStream[3]; 

     for(int i=0; i<3; i++) { 
      // connecting initially 
      System.out.println("Waiting for client "+i); 
      Socket client = welcome.accept(); 
      PrintWriter send = new PrintWriter(client.getOutputStream(),true); 
      BufferedReader receive = new BufferedReader(new InputStreamReader(client.getInputStream())); 

      // sending serial number 
      send.println(Integer.toString(i)); 

      // sending ports for thread sockets 
      send.println(Integer.toString(startSTport+i)); 
      send.println(Integer.toString(startUTport+i)); 

      // accepting sockets 
      tmpSocket = new ServerSocket(startSTport+i); 
      STsocket = tmpSocket.accept(); 
      tmpSocket = new ServerSocket(startUTport+i); 
      UTsocket = tmpSocket.accept(); 

      // creating communications 
      STmsgFrom[i] = new BufferedReader(new InputStreamReader(STsocket.getInputStream())); 
      STmsgTo[i] = new PrintWriter(STsocket.getOutputStream(),true); 
      STfileFrom[i] = new DataInputStream(STsocket.getInputStream()); 

      UTmsgFrom[i] = new BufferedReader(new InputStreamReader(UTsocket.getInputStream())); 
      UTmsgTo[i] = new PrintWriter(UTsocket.getOutputStream(),true); 
      UTfileTo[i] = new DataOutputStream(UTsocket.getOutputStream()); 

      System.out.println("Connected client "+i); 
     } 

     ClientThread ct0 = new ClientThread(0,STmsgFrom,STmsgTo,STfileFrom,UTmsgFrom,UTmsgTo,UTfileTo); 
     ClientThread ct1 = new ClientThread(1,STmsgFrom,STmsgTo,STfileFrom,UTmsgFrom,UTmsgTo,UTfileTo); 
     ClientThread ct2 = new ClientThread(2,STmsgFrom,STmsgTo,STfileFrom,UTmsgFrom,UTmsgTo,UTfileTo); 
     ct0.start(); 
     ct1.start(); 
     ct2.start(); 

     System.out.println("Server Stup Complete!"); 
    } 

} 

class ClientThread extends Thread { 
    String msg; 
    int cid; 
    BufferedReader[] STmsgFrom; 
    PrintWriter[] STmsgTo; 
    DataInputStream[] STfileFrom; 

    BufferedReader[] UTmsgFrom; 
    PrintWriter[] UTmsgTo; 
    DataOutputStream[] UTfileTo; 
    public ClientThread(int cid,BufferedReader[] STmsgFrom,PrintWriter[] STmsgTo,DataInputStream[] STfileFrom,BufferedReader[] UTmsgFrom,PrintWriter[] UTmsgTo,DataOutputStream[] UTfileTo) { 
     this.cid=cid; 

     this.STmsgFrom=STmsgFrom; 
     this.STmsgTo=STmsgTo; 
     this.STfileFrom = STfileFrom; 

     this.UTmsgFrom=UTmsgFrom; 
     this.UTmsgTo=UTmsgTo; 
     this.UTfileTo = UTfileTo; 
    } 

    @Override 
    public void run() { 
     while(true) { 
      try { 
       // receiving request from receiver UserThread 
       msg = UTmsgFrom[cid].readLine(); 
       if(msg.equals("get list")) { // receiver requested for file list 
        System.out.println("Request from "+cid+": "+msg); 
        for(int i=0; i<3; i++) { 
         if(i==cid) continue; 

         // sending request to sender ServerThread 
         STmsgTo[i].println("give list"); 
         System.out.println("Request to "+i); 

         // receive file count from sender ServerThread 
         int cnt = Integer.parseInt(STmsgFrom[i].readLine()); 
         System.out.println(i+" has files: "+cnt); 

         // sending source identity to receiver UserThread 
         UTmsgTo[cid].println(Integer.toString(i)); 

         // send file count back to receiver UserThread 
         UTmsgTo[cid].println(Integer.toString(cnt)); 

         // get and send file names to receiver 
         for(int j=0; j<cnt; j++) { 
          msg = STmsgFrom[i].readLine(); 
          UTmsgTo[cid].println(msg); 
         } 
        } 
       } else if(msg.equals("get file")) { 
        // get source id and filename 
        int source = Integer.parseInt(UTmsgFrom[cid].readLine()); 
        String fileName = UTmsgFrom[cid].readLine(); 
        //System.out.println("get source id and filename"); 

        // ask source about file 
        STmsgTo[source].println("give file"); 
        STmsgTo[source].println(fileName); 
        boolean fileOk = Boolean.parseBoolean(STmsgFrom[source].readLine()); 
        //System.out.println("ask source about file"); 

        // telling receiver about file status 
        UTmsgTo[cid].println(Boolean.toString(fileOk)); 
        //System.out.println("telling receiver about file"); 

        if(fileOk) { 
         // get copy request from receiver 
         msg = UTmsgFrom[cid].readLine(); 
         //System.out.println("receiver copy command"); 
         if(msg.equals("yes copy")) { 
          System.out.println("Copying \'"+fileName+"\' from "+source+" to "+cid); 
          // tell sender to copy 
          STmsgTo[source].println("yes copy"); 
          //System.out.println("tell sender copy command"); 

          // copy from SENDER 
          // get file size 
          int FILE_SIZE = Integer.parseInt(STmsgFrom[source].readLine()); 
          byte[] fileBytes = new byte[FILE_SIZE]; 
          System.out.println("Get file size "+FILE_SIZE); 
          // get file data 
          int portion = STfileFrom[source].read(fileBytes,0,fileBytes.length); 
          int position = portion; 
          do { 
           portion = STfileFrom[source].read(fileBytes,position,fileBytes.length-position); 
           if(portion>=0) { 
            position += portion; 
           } 
           System.out.println("position = "+position); 
          } while(position<FILE_SIZE); 
          System.out.println("Get file data "+position); 

          // copy to RECEIVER 
          // send file size 
          UTmsgTo[cid].println(Integer.toString(FILE_SIZE)); 
          //System.out.println("send file size"); 
          // send file data 
          UTfileTo[cid].write(fileBytes,0,position); 
          UTfileTo[cid].flush(); 
          //System.out.println("send file data"); 
          System.out.println("Copying \'"+fileName+"\' complete"); 
         } else { 
          // tell sender to ignore copy process 
          STmsgTo[source].println("no copy"); 
         } 
        } 
       } 
      } catch(Exception ex) { 
       ex.printStackTrace(); 
      } 
     } 
    } 
} 

客户:

package client; 
import java.io.*; 
import java.net.*; 

public class Client { 

    public static void main(String[] args) throws Exception { 
     String msg; 
     InetAddress inetAddress = InetAddress.getLocalHost(); 
     String[] allPaths= {"H:\\Study\\Lab\\Network\\Assingment 2 and lab of 5 july\\Assignment\\files\\client_1_folder", 
          "H:\\Study\\Lab\\Network\\Assingment 2 and lab of 5 july\\Assignment\\files\\client_2_folder", 
          "H:\\Study\\Lab\\Network\\Assingment 2 and lab of 5 july\\Assignment\\files\\client_3_folder"}; 

     // connecting to welcome socket 
     Socket server = new Socket(inetAddress,6000); 
     BufferedReader receive = new BufferedReader(new InputStreamReader(server.getInputStream())); 
     BufferedReader receiveUser = new BufferedReader(new InputStreamReader(System.in)); 
     PrintWriter send = new PrintWriter(server.getOutputStream(),true); 

     // receiving serial number 
     int cid = Integer.parseInt(receive.readLine()); 

     // receiving port numbers for thread sockets 
     int STport = Integer.parseInt(receive.readLine()); 
     int UTport = Integer.parseInt(receive.readLine()); 

     // connecting sockets 
     Socket STsocket = new Socket(inetAddress,STport); 
     Socket UTsocket = new Socket(inetAddress,UTport); 

     System.out.println("Connected to the server.\nSerial: "+cid+"\nFolder path: "+allPaths[cid]); 

     ServerThread st = new ServerThread(allPaths[cid],STsocket); 
     UserThread ut = new UserThread(cid,allPaths[cid],UTsocket); 
     st.start(); 
     ut.start(); 
    } 
} 

class UserThread extends Thread { 
    int cid; 
    String msg,folderPath; 
    BufferedReader msgFromServer,fromUser; 
    PrintWriter msgToServer; 
    // for file 
    DataInputStream fileFromServer; 
    BufferedOutputStream writeFile; 
    public UserThread(int cid,String folderPath,Socket socket) { 
     try { 
      this.cid = cid; 
      this.folderPath = folderPath; 
      fromUser = new BufferedReader(new InputStreamReader(System.in)); 
      msgFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
      msgToServer = new PrintWriter(socket.getOutputStream(),true); 
      // for file 
      fileFromServer = new DataInputStream(socket.getInputStream()); 
     } catch(Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 

    @Override 
    public void run() { 
     //System.out.println("User Thread Started!"); 
     while(true) { 
      try { 
       msg = fromUser.readLine(); 
       if(msg.equals("get list")) { 
        // sending request to server 
        msgToServer.println("get list"); 

        // getting file list from server 
        System.out.println("-------------------------------------------"); 
        for(int i=0; i<2; i++) { 
         // getting source id 
         int source = Integer.parseInt(msgFromServer.readLine()); 
         System.out.println("Source: "+source); 

         int cnt = Integer.parseInt(msgFromServer.readLine()); 
         System.out.println("Files: "+cnt); 
         System.out.println("--------------"); 

         for(int j=0; j<cnt; j++) { 
          msg = msgFromServer.readLine(); 
          System.out.println(msg); 
         } 
         System.out.println("-------------------------------------------"); 
        } 
       } else if(msg.equals("get file")) { 
        // GETTING A FILE 
        int source; 
        while(true) { 
         System.out.println("File Source: "); 
         try { 
          source = Integer.parseInt(fromUser.readLine()); 
          if(0<=source && source<=2 && source!=cid) { 
           break; 
          } else { 
           System.out.println("Error: File source invalid. Try again."); 
          } 
         } catch(Exception ex) { 
          System.out.println("Error: File source invalid. Try again."); 
         } 
        } 

        System.out.println("File Name: "); 
        String fileName = fromUser.readLine(); 

        // send request to server to check file 
        msgToServer.println("get file"); 
        msgToServer.println(Integer.toString(source)); 
        msgToServer.println(fileName); 

        // receiving file status 
        boolean fileOk = Boolean.parseBoolean(msgFromServer.readLine()); 
        if(!fileOk) { 
         System.out.println("Error: File does not exist at source."); 
        } else { 
         System.out.println("File is available!!"); 
         System.out.println("Want to copy \'"+fileName+"\'? (y/n)"); 
         msg = fromUser.readLine(); 
         if(msg.equals("y")||msg.equals("Y")) { 
          // tell server to copy file 
          msgToServer.println("yes copy"); 

          // COPY PROCESS 
          // get file size 
          int FILE_SIZE = Integer.parseInt(msgFromServer.readLine()); 
          System.out.println("File size: "+FILE_SIZE+" bytes."); 
          byte[] fileBytes = new byte[FILE_SIZE]; 

          // get file data 
          int portion = fileFromServer.read(fileBytes,0,fileBytes.length); 
          int position = portion; 
          do { 
           portion = fileFromServer.read(fileBytes,position,fileBytes.length-position); 
           if(portion>=0) { 
            position += portion; 
           } 
           System.out.println("position = "+position); 
          } while(position<FILE_SIZE); 
          System.out.println("Total "+position+" bytes received."); 

          // write file data 
          File file = new File(folderPath + "\\" + fileName); 
          writeFile = new BufferedOutputStream(new FileOutputStream(file)); 
          writeFile.write(fileBytes,0,position); 
          writeFile.flush(); 
          writeFile.close(); 

          System.out.println("Copying complete."); 
         } else { 
          msgToServer.println("no copy"); 
         } 
        } 
       } 
      } catch(Exception ex) { 
       ex.printStackTrace(); 
      } 
     } 
    } 
} 

class ServerThread extends Thread { 
    String msg,folderPath; 
    BufferedReader msgFromServer; 
    PrintWriter msgToServer; 
    // for file 
    DataOutputStream fileToServer; 
    BufferedInputStream readFile; 
    public ServerThread(String folderPath,Socket socket) { 
     try { 
      this.folderPath = folderPath; 
      msgFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
      msgToServer = new PrintWriter(socket.getOutputStream(),true); 
      // for file 
      fileToServer = new DataOutputStream(socket.getOutputStream()); 
     } catch(Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 

    @Override 
    public void run() { 
     //System.out.println("Server Thread Started!"); 
     while(true) { 
      try { 
       msg = msgFromServer.readLine(); 
       if(msg.equals("give list")) { 
        //System.out.println("Request from server: "+msg); 
        File folder = new File(folderPath); 
        File[] fileList = folder.listFiles(); 
        int cnt = fileList.length; 

        //System.out.println("Files: "+cnt); 

        // give file count back to server 
        msgToServer.println(Integer.toString(cnt)); 

        // give file list back to server 
        for(int i=0; i<cnt; i++) { 
         msgToServer.println(fileList[i].getName()); 
        } 
       } else if(msg.equals("give file")) { 
        // receive file name 
        String fileName = msgFromServer.readLine(); 

        // telling server about file status 
        File file = new File(folderPath + "\\" + fileName); 
        boolean fileOk = file.exists(); 
        msgToServer.println(Boolean.toString(fileOk)); 

        if(fileOk) { 
         // getting copy request 
         msg = msgFromServer.readLine(); 
         if(msg.equals("yes copy")) { 
          // COPY PROCESS 
          // send file size 
          int FILE_SIZE = (int)file.length(); 
          msgToServer.println(Integer.toString(FILE_SIZE)); 

          // read file data 
          readFile = new BufferedInputStream(new FileInputStream(file)); 
          byte[] fileBytes = new byte[FILE_SIZE]; 
          readFile.read(fileBytes,0,fileBytes.length); 
          readFile.close(); 

          // send file data 
          fileToServer.write(fileBytes,0,fileBytes.length); 
          fileToServer.flush(); 
         } // otherwise end of conversation 
        } 
       } 
      } catch(Exception ex) { 
       ex.printStackTrace(); 
      } 
     } 
    } 
} 

我知道我做喜欢的所有不同的插座给不同的端口一些不必要的东西。忽略它们,如果它们不是我问题的原因。

+0

@EJP - 这个问题如何重复?你甚至在这里花时间阅读这个问题? – ddhrubo

回答

0

ServerSocket.accept()被阻塞,您不能从同一个线程调用它两次。

每个ServerSocket必须运行在它自己的线程中。