0

我正在尝试将图像从“服务器”(其目的是发送图像)发送到作为 Android 设备的“客户端”。之间的套接字保持打开状态,图像不断出现。问题是:

  1. 我不知道图像的大小(它可以改变);
  2. 图像不是 BMP 格式。

在我下面的代码中:

  1. 客户端在图像传输后不会停止读取(-1读取时我没有得到),它会在套接字关闭时停止;
  2. 完成读取后,输入流不会被清除,并且会一遍又一遍地读取相同的图像。

起初,我尝试发送 2 个我知道大小的 BMP 图像(两者大小相同)。这是服务器代码:

    public static void main(String[] args) {
        try {
            ServerSocket s = new ServerSocket(4488);
            System.out.println("Waiting for a connection . . . . ");
            Socket socket = s.accept();
            System.out.println("Connected!");
            DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
            Thread.sleep(2000);

            File myImageFile = new File("c:\\1\\a.bmp");
            FileInputStream fis = new FileInputStream(myImageFile);
            byte[] data = new byte[(int) myImageFile.length()];
            byte[] tmp = new byte[0];
            byte[] myArrayImage = new byte[0];
            int len = 0 ;
            int total = 0;

            while( (len = fis.read(data)) != -1 ) {
                total += len;
                tmp = myArrayImage;
                myArrayImage = new byte[total];
                System.arraycopy(tmp,0,myArrayImage,0,tmp.length);
                System.arraycopy(data,0,myArrayImage,tmp.length,len);
            }

            //

            fis.close();

            dataOutputStream.write(myArrayImage);
            dataOutputStream.flush();
            Thread.sleep(2000);

            myImageFile = new File("c:\\1\\b.bmp");
            fis = new FileInputStream(myImageFile);
            data = new byte[(int) myImageFile.length()];
            tmp = new byte[0];
            myArrayImage = new byte[0];
            len = 0 ;
            total = 0;

            while( (len = fis.read(data)) != -1 ) {
                total += len;
                tmp = myArrayImage;
                myArrayImage = new byte[total];
                System.arraycopy(tmp,0,myArrayImage,0,tmp.length);
                System.arraycopy(data,0,myArrayImage,tmp.length,len);
            }

            fis.close();

            dataOutputStream.write(myArrayImage);
            dataOutputStream.flush();
            Thread.sleep(2000);

            socket.close();
            s.close();

这是客户端代码:

    @Override
public void run() {
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    byte[] byteChunk = null;
    int c;

    if (_dataInputStream != null) {
        while (true) {
            try {
                Thread.sleep(200);
            } catch (Exception e) {
            }

            try {
                byteChunk = new byte[1024];

                while ((c = _dataInputStream.read(byteChunk)) != -1){
                    buffer.write(byteChunk, 0, byteChunk.length);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }



            final Bitmap bitmap = BitmapFactory.decodeByteArray(buffer.toByteArray(), 0, buffer.size());

            if (bitmap != null) {
                _handler.post(new Runnable() {
                    public void run() {
                        _iv.setImageBitmap(bitmap);
                        _iv.invalidate();
                    }
                }); 
            }

                buffer.reset();
        }
    }
}

现在,正如我所说,客户端一直停留在 while 循环上,直到套接字关闭,然后(无论我发送多少图像,因为我在客户端创建了一个仅适合 1 个图像的字节数组)它一直在读取这个一直都是第一张图。

任何想法我做错了什么?

Ps 如果图像不是 BMP,我在客户端代码中编写的解码会起作用吗?我要发送的真实图像是PNG。

4

5 回答 5

1

您可以先发送图像字节数组的大小,然后在 while 循环中读取字节,直到达到如下大小:

DataInputStream in = conn.openDataInputStream();

            // read a length first
            int length = in.readInt();


            if (length <= 0) {
                throw new IOException("Can't read a length");
            }

            // read the image now
            imgData = new byte[length];
            length = 0;

            while (length != imgData.length) {
                int n = in.read(imgData, length, imgData.length - length);

                if (n == -1) {
                    throw new IOException("Can't read a image data");
                }

                length += n;
            }

            in.close();

这是这个的编辑版本

请注意图像的大小是 int 并且它有多个字节,那么您需要使用 writeint。

于 2013-05-22T07:20:59.753 回答
0

除非您使用某种机制来指示输入结束,否则客户端无法知道何时停止从流中读取。

一个简单的解决方法是使用一个固定长度(四个字节,一个 int 对大多数图像来说就足够了)标题,您将其写入流中,告诉客户端以下数据的长度。然后,客户端在停止并等待其他标头或关闭流之前从流中读取该字节数。

另一种方法是使用文件结束分隔符来通知客户端已经遇到输入的结尾。

除了图像本身之外,您还必须在流中写入一些额外的数据(元数据),除非您在输入后关闭流。

于 2012-06-12T07:43:38.867 回答
0

只查看了您的客户端代码,但这不适合评论。你需要重新考虑你在做什么;您的想法(我在第一次尝试时也这样)是基于人的而不是基于计算机的。换句话说,你的代码对这个人有意义,但我真的不知道为什么,它对计算机没有意义。

要点:你的while (true)循环没有出口——它是无限的。我希望它重复最后一次读入“位图”。

首先,我会摆脱sleep代码。现在这个问题令人困惑,如果它有帮助,您可以稍后将其放回去。(我不认为它会,你的阅读会做所有必要的阻塞。)然后你需要一个图像结束标记或其他东西来让你在读取完整图像时脱离读取循环。(或者让它触发放置这个循环中的图像处理代码。)

最后,您需要一个文件结束或图像结束标记来将您踢出while (true)循环。(回到“重点”。)

于 2012-06-13T18:12:36.490 回答
0

嗨,但如果你想阅读jpeg文件,那么你可以使用这个代码

byte[] bytes = new byte[1024 * 1024];
int count = 0;
do
{
    count += in.read(bytes, count, bytes.length - count);
}while (!(count > 4 && bytes[count - 2] == (byte) -1 && bytes[count - 1] == (byte) -39));

但我无法理解如何阅读PNG格式

于 2012-07-02T06:24:28.200 回答
-1

如果您想发送 PNG,请阅读有关格式 ( Wiki ) 的一些信息。每个块都带有长度前缀,因此您可以通过网络将其原始发送并知道它何时完成!

于 2012-06-12T08:57:44.080 回答