1

我创建了一个 Android 应用程序,其中 Android 应用程序充当客户端,服务器驻留在桌面上。我正在使用套接字编程进行通信。我已成功在客户端和服务器之间传输消息,但我不知道如何传输图像。我需要将图像文件从服务器发送到客户端,而不是从客户端发送到服务器

谁能帮我解决从服务器向客户端发送 png 图像的解决方案?

到目前为止,这是我的代码:

客户端

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();
                }
            }

        }

服务器类

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();
            }

        }

    }
4

1 回答 1

4

在这里,您有从服务器到客户端发送/接收(图像)文件的服务器和客户端代码。客户端将图像保存在外部存储中,如果您想将其保存在其他地方,请更改它。客户端函数返回接收到的图像的位图,您也可以通过注释代码中的行来避免这种情况。

要使用这些函数,请使用类似于以下内容的内容:

注意这两个函数必须从主 UI 线程以外的线程调用:

// 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();
}

接收函数:(复制粘贴到客户端)

/**
 * 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();
    }
}

sender函数:(复制粘贴到服务器端)

/**
 * 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();
    }
}
于 2013-09-03T16:36:46.487 回答