通过socket编程从服务器(桌面)客户端(安卓)发送PNG图像文件 [英] sending png image file from server (desktop) to client (android) via socket programming

查看:178
本文介绍了通过socket编程从服务器(桌面)客户端(安卓)发送PNG图像文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经创建其中Android应用程序作为客户端和服务器驻留在桌面上的Andr​​oid应用程序。我使用套接字编程进行通信。我已经成功地转移客户端和服务器之间的消息,但我不知道如何将图像传输。 我需要从服务器发送图像文件给客户端,而不是从客户机到服务器

任何人都可以请帮我解决从服务器发送一个PNG图像客户端?

这是我的code迄今:

客户端

 私人INT SERVER_PORT = 9999;
类客户端实现Runnable {
            私人客户端的Socket;
            私人的PrintWriter出来;
            私下扫描仪;            @覆盖
            公共无效的run(){
                尝试{
                    客户端=新的Socket(localhost的,SERVER_PORT);
                    Log.d(客户,连接到服务器端口+ SERVER_PORT);
                    OUT =的新PrintWriter(client.getOutputStream());
                    在=新扫描仪(client.getInputStream());
                    串线;                    而((行= in.nextLine())!= NULL){
                        Log.d(客户端,服务器云:+线);
                        如果(line.equals(你好客户)){
                            通过out.println(回复);
                            了out.flush();
                        }
                    }                }赶上(UnknownHostException异常五){
                    // TODO自动生成catch块
                    e.printStackTrace();
                }赶上(IOException异常五){
                    // TODO自动生成catch块
                    e.printStackTrace();
                }
            }        }

服务器类

 类ServerThread实现Runnable {
        私人ServerSocket的服务器;        @覆盖
        公共无效的run(){
            尝试{
                服务器=新的ServerSocket(SERVER_PORT);
                Log.d(服务器,开始在端口的服务器+ SERVER_PORT
                        +和等待客户端...);
                而(真){
                    Socket套接字= server.accept();
                    Log.d(服务器,
                            接受socket连接:
                                    + socket.getLocalAddress());
                    新主题(新的ClientHandler的(插座))开始()。
                }
            }赶上(IOException异常五){
                // TODO自动生成catch块
                e.printStackTrace();
            }
        }    }    类ClientHandler中实现Runnable {        私人插座ClientSocket的;
        私人的PrintWriter出来;
        私下扫描仪;        公共ClientHandler中(插座clietSocket){
            this.clientSocket = clietSocket;
        }        @覆盖
        公共无效的run(){
            尝试{
                OUT =的新PrintWriter(clientSocket.getOutputStream());
                在=新扫描仪(clientSocket.getInputStream());
                串线;
                Log.d(ClientHandlerThread,与开始通讯:
                        + clientSocket.getLocalAddress());
                通过out.println(你好客户);
                了out.flush();
                而((行= in.nextLine())!= NULL){
                    Log.d(ClientHandlerThread,客户说:+线);
                    如果(line.equals(回复)){
                        的out.print(服务器篇);
                        了out.flush();
                    }
                }
            }赶上(IOException异常五){
                // TODO自动生成catch块
                e.printStackTrace();
            }        }    }


解决方案

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

要使用的功能,使用类似下面的内容:

请注意这两个功能必须从非主UI线程以外的线程调用:

  //接收文件
尝试
{
    //文件名必须是简单的文件名,不文件分隔符'/'
    receiveFile(myClientSocket.getInputStream(),myImage.png);
}
赶上(例外五)
{
    e.printStackTrace();
}//发送文件
尝试
{
    //文件名必须是一个完全合格的路径
    SENDFILE(myServerSocket.getOutputStream(),C:/MyImages/orange.png);
}
赶上(例外五)
{
    e.printStackTrace();
}

该接收器功能:(复制并粘贴到客户端)

  / **
 *从连接的插座接收图像文件并将其保存到一个文件中。
 *所述p为H.;
 *它接收到的第一个4字节表示文件的大小
 * LT; / P>
 *
 * @参数是
 *从连接插座的InputStream
 * @参数文件名
 *文件的名称在外部存储保存,不
 *文件分割符
 * @返回位图重新presenting图像接收o原在出现错误的情况下,
 * @throws异常
 * @see {@link SENDFILE}为例如何将文件在对方发送。
 *
 * /
公共位图receiveFile(InputStream为,字符串文件名)抛出异常
{字符串BASEDIR = Environment.getExternalStorageDirectory()getAbsolutePath()。
    字符串fileInES = BASEDIR +文件分割符+文件名;    //读取包含文件的大小4个字节
    字节[] = BSIZE新的字节[4];
    INT偏移= 0;
    而(偏移< bSize.l​​ength)
    {
        INT面包= is.​​read(BSIZE,偏移,bSize.l​​ength - 偏移);
        胶印+ =面包;
    }
    //将4个字节为int
    INT档案大小;
    档案大小=(int)的(BSIZE [0]&放大器; 0xff的)下;&下; 24
               | (中间体)(BSIZE [1]&安培; 0xff的)下;&下; 16
               | (中间体)(BSIZE [2]&放大器; 0xff的)下;&下; 8
               | (中间体)(BSIZE [3]&放大器; 0xff的);    //缓冲区从套接字读取
    // 8K缓冲区足够好
    字节[]数据=新的字节[8 * 1024];    INT bToRead;
    FOS的FileOutputStream =新的FileOutputStream(fileInES);
    BOS的BufferedOutputStream =新的BufferedOutputStream(FOS);
    而(档案大小大于0)
    {
        //确保不读文件大小超过多个字节
        如果(档案大小> data.length)bToRead = data.length;
        否则bToRead =档案大小;
        INT读取动作= is.​​read(数据,0,bToRead);
        如果(读取动作大于0)
        {
            bos.write(数据,0,读取动作);
            档案大小 - =读取动作;
        }
    }
    bos.close();    //接收到的图像转换为位图
    //如果你不想返回一个位图注释/删除如下因素线
    //并使函数返回void或任何你preFER。
    BMP位图= NULL;
    FIS的FileInputStream =新的FileInputStream(fileInES);
    尝试
    {
        BMP = BitmapFactory.de codeStream(FIS);
        返回BMP;
    }
    最后
    {
        fis.close();
    }
}

发送器功能:(复制并粘贴到服务器端)

  / **
 *将文件发送到连接的插座。
 *所述p为H.;
 *首先,它在发送4个字节的文件大小则该文件的内容。
 * LT; / P>
 *所述p为H.;
 *注:文件大小限制为32位有符号整数,2GB
 * LT; / P>
 *
 * @参数OS
 *连接插座的OutputStream
 * @参数文件名
 *图像的完整文件的路径发送
 * @throws异常
 * @see {@link receiveFile}一个例子,如何在对方收到的文件。
 *
 * /
公共无效SENDFILE(OutputStream的OS,字符串文件名)抛出异常
{
    //要发送的文件
    myfile文件=新的文件(文件名);
    INT FSIZE =(int)的myFile.length();
    如果(FSIZE&下; myFile.length())
    {
        的System.out.println(文件过大');
        抛出新IOException异常(文件太大了。);
    }    //发送文件的大小
    字节[] = BSIZE新的字节[4];
    BSIZE [0] =(字节)((FSIZE&放大器; 0xff000000)GT;> 24);
    BSIZE [1] =(字节)((FSIZE&放大器; 0x00ff0000)GT;> 16);
    BSIZE [2] =(字节)((FSIZE&放大器; 0x0000ff00)GT;→8);
    BSIZE [3] =(字节)(FSIZE&放大器; 0x000000ff);
    包含文件大小// 4字节
    os.write(BSIZE,0,4);    //在内存的限制情况下,这个设置为false
    布尔noMemoryLimitation = TRUE;    FIS的FileInputStream =新的FileInputStream(MYFILE);
    二BufferedInputStream为=新的BufferedInputStream(FIS);
    尝试
    {
        如果(noMemoryLimitation)
        {
            //用来发送整个文件中的一个块
            字节[] = outBuffer新的字节[FSIZE]
            INT面包= bis.read(outBuffer,0,outBuffer.length);
            os.write(outBuffer,0,面包);
        }
        其他
        {
            //使用在一个小缓冲区发送,块数
            INT面包= 0;
            字节[] = outBuffer新的字节[8 * 1024];
            而((面包= bis.read(outBuffer,0,outBuffer.length))大于0)
            {
                os.write(outBuffer,0,面包);
            }
        }
        os.flush();
    }
    最后
    {
        bis.close();
    }
}

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

这篇关于通过socket编程从服务器(桌面)客户端(安卓)发送PNG图像文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆