简体   繁体   中英

sending png image file from server (desktop) to client (android) via socket programming

I've created an android application in which the Android application acts as the client and server resides on a desktop. I'm using socket programming for communication. I've successfully transferred messages between client and server, but I don't know how to transfer an image. I need to send image file from server to client , not from client to server

Can anyone please help me with the solution for sending a png image from server to client?

This is my code so far:

Client side

private int SERVER_PORT = 9999;
class Client implements Runnable {
            private Socket client;
            private PrintWriter out;
            private Scanner in;

            @Override
            public void run() {
                try {
                    client = new Socket("localhost", SERVER_PORT);
                    Log.d("Client", "Connected to server at port " + SERVER_PORT);
                    out = new PrintWriter(client.getOutputStream());
                    in = new Scanner(client.getInputStream());
                    String line;

                    while ((line = in.nextLine()) != null) {
                        Log.d("Client", "Server says: " + line);
                        if (line.equals("Hello client")) {
                            out.println("Reply");
                            out.flush();
                        }
                    }

                } catch (UnknownHostException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

        }

Server class

class ServerThread implements Runnable {
        private ServerSocket server;

        @Override
        public void run() {
            try {
                server = new ServerSocket(SERVER_PORT);
                Log.d("Server", "Start the server at port " + SERVER_PORT
                        + " and waiting for clients...");
                while (true) {
                    Socket socket = server.accept();
                    Log.d("Server",
                            "Accept socket connection: "
                                    + socket.getLocalAddress());
                    new Thread(new ClientHandler(socket)).start();
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

    class ClientHandler implements Runnable {

        private Socket clientSocket;
        private PrintWriter out;
        private Scanner in;

        public ClientHandler(Socket clietSocket) {
            this.clientSocket = clietSocket;
        }

        @Override
        public void run() {
            try {
                out = new PrintWriter(clientSocket.getOutputStream());
                in = new Scanner(clientSocket.getInputStream());
                String line;
                Log.d("ClientHandlerThread", "Start communication with : "
                        + clientSocket.getLocalAddress());
                out.println("Hello client");
                out.flush();
                while ((line = in.nextLine()) != null) {
                    Log.d("ClientHandlerThread", "Client says: " + line);
                    if (line.equals("Reply")){
                        out.print("Server replies");
                        out.flush();
                    }
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

    }

Here you have server and client codes that send/receive (image) files from server to client. Client save the image in external storage, change that if you want to save it somewhere else. The client function returns a Bitmap of the received image, you can also avoid this by commenting the lines in the code.

To use the functions, use something similar to the following:

NOTE these two function must be called from a thread other than the main UI thread:

// To receive a file
try
{
    // The file name must be simple file name, without file separator '/'
    receiveFile(myClientSocket.getInputStream(), "myImage.png");
}
catch (Exception e)
{
    e.printStackTrace();
}

// to send a file
try
{
    // The file name must be a fully qualified path
    sendFile(myServerSocket.getOutputStream(), "C:/MyImages/orange.png");
}
catch (Exception e)
{
    e.printStackTrace();
}

The receiver function: (Copy and paste it to the client side)

/**
 * Receive an image file from a connected socket and save it to a file.
 * <p>
 * the first 4 bytes it receives indicates the file's size
 * </p>
 * 
 * @param is
 *           InputStream from the connected socket
 * @param fileName
 *           Name of the file to save in external storage, without
 *           File.separator
 * @return Bitmap representing the image received o null in case of an error
 * @throws Exception
 * @see {@link sendFile} for an example how to send the file at other side.
 * 
 */
public Bitmap receiveFile(InputStream is, String fileName) throws Exception
{

String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
    String fileInES = baseDir + File.separator + fileName;

    // read 4 bytes containing the file size
    byte[] bSize = new byte[4];
    int offset = 0;
    while (offset < bSize.length)
    {
        int bRead = is.read(bSize, offset, bSize.length - offset);
        offset += bRead;
    }
    // Convert the 4 bytes to an int
    int fileSize;
    fileSize = (int) (bSize[0] & 0xff) << 24 
               | (int) (bSize[1] & 0xff) << 16 
               | (int) (bSize[2] & 0xff) << 8
               | (int) (bSize[3] & 0xff);

    // buffer to read from the socket
    // 8k buffer is good enough
    byte[] data = new byte[8 * 1024];

    int bToRead;
    FileOutputStream fos = new FileOutputStream(fileInES);
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    while (fileSize > 0)
    {
        // make sure not to read more bytes than filesize
        if (fileSize > data.length) bToRead = data.length;
        else bToRead = fileSize;
        int bytesRead = is.read(data, 0, bToRead);
        if (bytesRead > 0)
        {
            bos.write(data, 0, bytesRead);
            fileSize -= bytesRead;
        }
    }
    bos.close();

    // Convert the received image to a Bitmap
    // If you do not want to return a bitmap comment/delete the folowing lines
    // and make the function to return void or whatever you prefer.
    Bitmap bmp = null;
    FileInputStream fis = new FileInputStream(fileInES);
    try
    {
        bmp = BitmapFactory.decodeStream(fis);
        return bmp;
    }
    finally
    {
        fis.close();
    }
}

The sender function: (copy and paste it to the server side)

/**
 * Send a file to a connected socket.
 * <p>
 * First it sends file size in 4 bytes then the file's content.
 * </p>
 * <p>
 * Note: File size is limited to a 32bit signed integer, 2GB
 * </p>
 * 
 * @param os
 *           OutputStream of the connected socket
 * @param fileName
 *           The complete file's path of the image to send
 * @throws Exception
 * @see {@link receiveFile} for an example how to receive file at other side.
 * 
 */
public void sendFile(OutputStream os, String fileName) throws Exception
{
    // File to send
    File myFile = new File(fileName);
    int fSize = (int) myFile.length();
    if (fSize < myFile.length())
    {
        System.out.println("File is too big'");
        throw new IOException("File is too big.");
    }

    // Send the file's size
    byte[] bSize = new byte[4];
    bSize[0] = (byte) ((fSize & 0xff000000) >> 24);
    bSize[1] = (byte) ((fSize & 0x00ff0000) >> 16);
    bSize[2] = (byte) ((fSize & 0x0000ff00) >> 8);
    bSize[3] = (byte) (fSize & 0x000000ff);
    // 4 bytes containing the file size
    os.write(bSize, 0, 4);

    // In case of memory limitations set this to false
    boolean noMemoryLimitation = true;

    FileInputStream fis = new FileInputStream(myFile);
    BufferedInputStream bis = new BufferedInputStream(fis);
    try
    {
        if (noMemoryLimitation)
        {
            // Use to send the whole file in one chunk
            byte[] outBuffer = new byte[fSize];
            int bRead = bis.read(outBuffer, 0, outBuffer.length);
            os.write(outBuffer, 0, bRead);
        }
        else
        {
            // Use to send in a small buffer, several chunks
            int bRead = 0;
            byte[] outBuffer = new byte[8 * 1024];
            while ((bRead = bis.read(outBuffer, 0, outBuffer.length)) > 0)
            {
                os.write(outBuffer, 0, bRead);
            }
        }
        os.flush();
    }
    finally
    {
        bis.close();
    }
}

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