title: -Java- Data 'loss' in TCP (strange, since TCP doesn't allow the data to escape)
body: <p>first of all, I know there are already a couple of posts here about similar issues, but I've gone through them and their problems were not mine nor their solutions solve my problem. If anyone has a post which solves my question, please reply with the link and I'll go for it.</p>
  
  <p>Now, the problem - I've got a client and a server. The client requests a file, the server sends it and then the client receives it, or at least that's how it should be. But it is not. What happens instead? The client receives the first 1024 bytes, then the next 1024 bytes, and then receives 436 bytes (I'm always using the same file so I always get the same results) and ends because it has received less than 1024 bytes and therefore it has deducted than it was the last read it had to perform, but it shouldn't be, because the server, when reading the file from its FileInputStream, reads much more bytes (much more pieces of 1024 bytes). I've tried everything I've imagined, but I've got no positive result: Always, the third piece, instead of being whole received, is just received up to the byte 436 (maybe what happens is that, from the third piece up to the penultimate are skipped for some reason, and then the last one is 436 bytes and is received, althought I don't think this is the case since the whole file isn't read in the server because the client closes the connection as soon as it thinks the transmission has finished, provoking an exception on the server that interrupts it from reading anything).</p>
  
  <p>And here goes what I think is the key code:</p>
  
  <p>Server</p>
  
  <pre><code>OutputStream put;
          try {
              ServerSocket serverSocket;
              try {
                  serverSocket = new ServerSocket(DesktopClient.PORT_FOR_FILES);
              } catch (IOException ex) {
                  JOptionPane.showMessageDialog(null, ex.toString(), "Error", JOptionPane.ERROR_MESSAGE);
                  return false;
              }
              Socket socket;
              try {
                  socket = serverSocket.accept();
                  ActionWindow.println("Connection for files transference stablished - " + socket);
              } catch (Exception ex) {
                  JOptionPane.showMessageDialog(null, ex.toString(), "Error", JOptionPane.ERROR_MESSAGE);
                  return false;
              }
              put = socket.getOutputStream();
              BufferedReader requestedVideoBufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
              String requiredVideo = requestedVideoBufferedReader.readLine();
              while (!requiredVideo.matches("finish") &amp;&amp; !requiredVideo.matches("errored")) {
                  ActionWindow.println("The screen in the router " + ActionWindow.currentConn + " is asking for " + requiredVideo);
                  if (new File(ActionWindow.pathToVideosFolder + requiredVideo + ActionWindow.videoFilesExtension).exists()) {
                      try (InputStream in = new FileInputStream(ActionWindow.pathToVideosFolder + requiredVideo + ActionWindow.videoFilesExtension)) {
                          byte[] buf = new byte[1024];
                          int len;
                          System.out.println("About to write");
                          while (true) {
                              len = in.read(buf);
                              System.out.println("len: " + len);
                              if (len &gt; 0) {
                                  put.write(buf, 0, len);
                              } else {
                                  break;
                              }
                          }
                      }
                      ActionWindow.println("File " + requiredVideo + ActionWindow.videoFilesExtension + " sent.");
                  } else {
                      ActionWindow.println("File " + requiredVideo + ActionWindow.videoFilesExtension + " couldn't be found in the local index.");
                      put.close();
                      socket.close();
                      serverSocket.close();
                      return false;
                  }
                  requiredVideo = requestedVideoBufferedReader.readLine();
              }
              if (requiredVideo.matches("errored")) {
                  JOptionPane.showMessageDialog(null, "Se produjo un error en la transmisión de archivos. Los datos del servidor no han sido modificados.", "Error", JOptionPane.ERROR_MESSAGE);
              }
              put.close();
              socket.close();
              serverSocket.close();
              ActionWindow.println("Connecion finished.");
          } catch (IOException ex) {
              if (!(ex instanceof SocketException)) { //This means that the exception has not been caused by finishing the transference.
                  JOptionPane.showMessageDialog(null, ex.toString(), "Error", JOptionPane.ERROR_MESSAGE);
                  return false;
              } else {
                  return true;
              }
          }
          return true;
  </code></pre>
  
  <p>Client</p>
  
  <pre><code>fileRequester.println(x);
              ServerDaemon.println("Requested " + x);
              File destFile = new File(ServerDaemon.pathToVideosFolder + x + ServerDaemon.videoFilesExtension);
              byte[] buf = new byte[1024];
              OutputStream streamForWritingToFile;
              try {
                  streamForWritingToFile = new FileOutputStream(destFile);
              } catch (FileNotFoundException ex) {
                  ServerDaemon.println(ex.toString());
                  return false;
              }
              int len;
              try {
                  while (true) {
                      len = streamFromServer.read(buf);
  
                      if (len &gt; 0) {
                          streamForWritingToFile.write(buf, 0, len);
                      } else {
                          break;
                      }
  
                      if (len != 1024) {
                          break;
                      }
                  }
              } catch (IOException ex) {
                  ServerDaemon.println(ex.toString());
                  if (ex instanceof SocketException) {
                      ServerDaemon.disconnect();
                  }
                  return false;
              }
  
              ServerDaemon.println("Received file " + x);
  </code></pre>
  
  <p>EDIT: As a temporal solution, I'm sending the file size through UDP so the receiver know how much data must it wait for. However, it's higly preferred to have it working through TCP, but it doesn't work (take a look at the comments in @PeterLawrey 's answer). This is what I've tried in order to make it work through TCP:</p>
  
  <p>Receiver:</p>
  
  <pre><code>BufferedReader inFromClient;
  int fileSize;
  String receivedSizeMsg = null;
  try {
        inFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        receivedSizeMsg = inFromClient.readLine();
      } catch (IOException ex) {
        ServerDaemon.println(ex.toString());
      }
  fileSize = Integer.parseInt(receivedSizeMsg.substring(4));
  </code></pre>
  
  <p>Sender:</p>
  
  <pre><code>DataOutputStream outToServer;
  outToServer = new DataOutputStream(socket.getOutputStream());
  outToServer.writeBytes("size" + new File(file+"\n");
  </code></pre>
  
  <p>SECOND EDIT: With TCP:</p>
  
  <p>Receiver:</p>
  
  <pre><code>DataInputStream inFromClient;
  int fileSize = 0;
  inFromClient = new DataInputStream(socket.getInputStream());
  fileSize = Integer.parseInt(inFromClient.readUTF().substring(4));
  </code></pre>
  
  <p>Sender:</p>
  
  <pre><code>DataOutputStream outToServer;
  outToServer = new DataOutputStream(socket.getOutputStream());
  outToServer.writeUTF("size" + new File(ActionWindow.pathToVideosFolder + requiredVideo + ActionWindow.videoFilesExtension).length());
  </code></pre>