简体   繁体   中英

Send file over socket (with threading on server-side) - not working

I have a Client-Server programm. The Client-programm sends a file to the server and the server receives the file. my problem is, that the file is not really receiving on the server...I't creates a file.txt in the server-directory, but it is empty...(yes i'm sure that ne file.txt in the client-directory is not empty ;) ) I think the problem is the while-loop in Client.java, because it is never embarrassed....

For the future i implements now on the server side one thread per receiving file.

The client-programm:

   package controller;

   public class Main {

       public static void main(String[] args) {
           new Controller();
    }

}

-

    package controller;

    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.PrintStream;
    import java.net.Socket;
    import java.net.UnknownHostException;



    public class Controller {

        public Controller() {
            try {
                sendFileToServer(); 
            } catch (IOException e) {
                e.printStackTrace();
            }  

        }

        public void sendFileToServer() throws UnknownHostException, IOException {
            Socket socket = null;
            String host = "localhost";

            socket = new Socket(host, 5555);    

            String filename = "file.txt";       
            File file = new File(filename); 

            OutputStream outText = socket.getOutputStream();
            PrintStream outTextP = new PrintStream(outText);
            outTextP.println(filename);

            long filesize = file.length();    
            byte[] bytes = new byte[(int) filesize];        
            FileInputStream fis = new FileInputStream(file);
            BufferedInputStream bis = new BufferedInputStream(fis);     

            BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());

            int count;
            System.out.println("Start sending file...");

            while ((count = bis.read(bytes)) > 0) {         
                System.out.println("count: " + count);
                out.write(bytes, 0, count);
            }
            System.out.println("Finish!");

            out.flush();

            out.close();
            fis.close();
            bis.close();
            socket.close();
        }


    }

-

The server-programm:

    import java.io.IOException;


    public class Main {

        public static void main(String[] args) throws IOException {
            new Server();
        }

    }

-

    public class Server {

        private ServerSocket serverSocket;

        public Server()  {
            try {
                serverSocket = new ServerSocket(5555);
                waitForClient();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

        private void waitForClient() {
            Socket socket = null;

            try {

                while(true) {
                    socket = serverSocket.accept();     
                    Thread thread = new Thread(new Client(socket));
                    thread.start(); 
                }

            } catch (IOException ex) {
                System.out.println("serverSocket.accept() failed!");
            }
        }

    }

-

    import java.io.BufferedOutputStream;
    import java.io.BufferedReader;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.Socket;

    public class Client implements Runnable{

        private Socket socket;

        public Client(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            receiveFile();   
        }

        private void receiveFile()  {
            try {

                InputStream is = null;
                FileOutputStream fos = null;
                BufferedOutputStream bos = null;
                int bufferSize = 0;

                InputStream outText = socket.getInputStream();      

                // Get filename
                InputStreamReader outTextI = new InputStreamReader(outText);
                BufferedReader inTextB = new BufferedReader(outTextI);
                String dateiname = inTextB.readLine();
                System.out.println("Dateiname: " + dateiname);

                try {
                    is = socket.getInputStream();           

                    bufferSize = socket.getReceiveBufferSize();
                    System.out.println("Buffer size: " + bufferSize);
                } catch (IOException ex) {
                    System.out.println("Can't get socket input stream. ");
                }

                try {
                    fos = new FileOutputStream(dateiname);  
                    bos = new BufferedOutputStream(fos);

                } catch (FileNotFoundException ex) {
                    System.out.println("File not found.");
                }

                byte[] bytes = new byte[bufferSize];

                int count;

                while ((count = is.read(bytes)) > 0) {          
                    bos.write(bytes, 0, count);                 
                    System.out.println("This is never shown!!!");   // In this while-loop the file is normally receiving and written to the directory. But this loop is never embarrassed...                                                                        
                }

                bos.flush();

                bos.close();
                is.close();
                socket.close();
            }catch(IOException e) {
                e.printStackTrace();
            }
        }

    }

When you do these kind of transfers you have to keep in mind that there is a difference between a socket's close and shutdown , in your code you close the socket in the client.

So lets see what happens : you fill in the buffers then you tell the socket to close which will discard the operation you just asked for. When you shutdown you tell the socket "I won't send more data but send what's left to be sent and shut down" so what you need to do is to shut down the socket before you close it so the data will arrive.

So instead of this

out.flush();

out.close();
fis.close();
bis.close();
socket.close();

Try it with this

out.flush();

socket.shutdownInput();    // since you only send you may not need to call this
socket.shutdownOutput();   // with this you ensure that the data you "buffered" is sent
socket.close();

Generally if you want a graceful close, you should do it like this in all cases even for the server, so what you did is usually okay if there is an error and you just close the connection since you cant recover from an error.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM