【问题标题】:How do I send Images over socket without closing the socket?如何在不关闭套接字的情况下通过套接字发送图像?
【发布时间】:2020-01-10 13:50:43
【问题描述】:

我已成功发送小(小于约 22mb)图像,但在发送较大图像时出现如下所示的错误。我希望能够重用套接字,因此不关闭它。

正如您可能看到的,我正在尝试将图片从客户端发送到服务器,如果我在控制台中键入 s,它将在服务器上显示。

javax.imageio.IIOException: 读取 PNG 图像数据时出错

在 java.desktop/com.sun.imageio.plugins.png.PNGImageReader.readImage(未知来源)
在 java.desktop/com.sun.imageio.plugins.png.PNGImageReader.read(未知来源)
在 java.desktop/javax.imageio.ImageIO.read(未知来源)
在 java.desktop/javax.imageio.ImageIO.read(未知来源)
在 lärning5.Server.main(Server.java:55)

原因:java.io.EOFException: ZLIB 输入流意外结束

在 java.base/java.util.zip.InflaterInputStream.fill(Unknown Source)
在 java.base/java.util.zip.InflaterInputStream.read(未知来源)
在 java.base/java.io.BufferedInputStream.fill(Unknown Source)
在 java.base/java.io.BufferedInputStream.read1(未知来源)
在 java.base/java.io.BufferedInputStream.read(Unknown Source)
在 java.base/java.io.DataInputStream.readFully(未知来源)
在 java.desktop/com.sun.imageio.plugins.png.PNGImageReader.decodePass(未知来源)
在 java.desktop/com.sun.imageio.plugins.png.PNGImageReader.decodeImage(未知来源)
... 5 更多

我尝试使用ObjectOutputStream 将图像作为对象发送,最终需要关闭套接字。我还尝试扩大缓冲区,以便它们能够容纳这么多内存。我尝试过使用ByteArrayInputStreamByteArrayOutputStream“正确的方式”,其中我获得了ByteArray 的大小,但我总是得到相同的错误消息。

尽量忽略cmets

服务器代码

package lärning5;

import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Server 
{

    static ServerSocket servern;
    static Socket client = new soketen();
    static OutputStream out;
    static InputStream in;
    static JFrame fön = new JFrame();
    static Panelen pan = new Panelen();
    static BufferedImage picture;
    static Scanner read = new Scanner(System.in);

    public static void main(String args[]) 
    {
        try 
        {
            servern = new ServerSocket(7777, 9999);
            client = servern.accept();
            System.out.print("conectad");


            out = client.getOutputStream();
            out.flush();
            in = client.getInputStream();

            byte[] buffer = new byte[899999];

            in.read(buffer, 0, buffer.length);
            ByteArrayInputStream bil = new ByteArrayInputStream(buffer, 0, buffer.length);
            picture = ImageIO.read(bil);

        } catch (Exception e) 
        {
            System.out.print("gg wp ");
            e.printStackTrace();
        }

        if (read.nextLine().equals("s"))
        {

            fön.setSize(Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height);
            fön.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            fön.add(pan);
            fön.repaint();
            fön.setVisible(true);
        }
    }
}

客户端代码

package lärning6;

import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;

public class Client 
{

    static Socket servern;
    static OutputStream out;
    static InputStream in;
    static Robot datorn;
    static BufferedImage picture;
    static ImageInputStream bil;
    static File fil = new File("src\\bilder\\ddeee.PNG");


    public static void main(String args[])
    {


        try
        {

            servern = new Socket(InetAddress.getByName("the ip address"), 7777);
            out = servern.getOutputStream();
            out.flush();
            in = servern.getInputStream();

            //byte[] buffer = new byte[90000];

            ByteArrayOutputStream bil = new ByteArrayOutputStream();
            picture = ImageIO.read(fil);//datorn.createScreenCapture(new Rectangle(0, 0, 500, 500));

            ImageIO.write(bild, "PNG", bil);


            out.write(bil.toByteArray());
            /*
            bil = ImageIO.createImageInputStream(picture);
            //bil.read(buffer, 0, buffer.length);
            ImageOutputStream bil = null;

            ImageIO.write(picture, "png", bil);
            buffer = bil.*/

        }catch(Exception e)
        {
            System.out.print("gg wr");
            e.printStackTrace();
        }

    }

}

面板

package lärning5;

import java.awt.Graphics;

import javax.swing.JPanel;

public class Panelen extends JPanel
{

    public void paintComponent(Graphics g)
    {

        g.drawImage(Server.picture, 0, 0, this.getWidth(), this.getHeight(), null);
    }
}

上面的代码和下面的代码是两个不同的代码,不应合并

下面的代码是使用适应图片大小的缓冲区的代码。

服务器

package lärning5;

import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.Scanner;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Server 
{

    static ServerSocket servern;
    static Socket client = new soketen();
    static OutputStream out;
    static InputStream in;
    static JFrame window = new JFrame();
    static Panelen panel = new Panelen();
    static BufferedImage bild;
    static File fil = new File("src\\bilde\\bilden.jpg");
    static Scanner läs = new Scanner(System.in);

    public static void main(String args[]) 
    {
        try 
        {
            servern = new ServerSocket(7777, 9999);
            client = servern.accept();
            System.out.print("conectad");


            out = client.getOutputStream();
            out.flush();
            in = client.getInputStream();

            byte[] buffer = new byte[4];
            //in.read(buffer);

            //ImageOutputStream bil = ImageIO.createImageOutputStream(bild);
            in.read(buffer);

            byte[] buffer2 = new byte[ByteBuffer.wrap(buffer).asIntBuffer().get()];

            in.read(buffer2);

            ImageIO.write(ImageIO.read(new ByteArrayInputStream(buffer2)), "PNG", new File("C:\\Users\\Bodi\\Desktop\\testse"));
            bild = ImageIO.read(new ByteArrayInputStream(buffer2));

        } catch (Exception e) 
        {
            System.out.print("gg wp ");
            e.printStackTrace();
        }

        if (läs.nextLine().equals("s"))
        {

            window.setSize(Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height);
            window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            window.add(panel);
            window.repaint();
            window.setVisible(true);
        }
    }
}

客户


package lärning6;

import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;

public class Client 
{

    static Socket servern;
    static OutputStream out;
    static InputStream in;
    static Robot datorn;
    static BufferedImage picture;
    static ImageInputStream bil;
    static File fil = new File("src\\bilder\\dddd.PNG");


    public static void main(String args[])
    {


        try
        {

            servern = new Socket(InetAddress.getByName("The ip adress"), 7777);
            out = servern.getOutputStream();
            out.flush();
            in = servern.getInputStream();

            //byte[] buffer = new byte[90000];

            ByteArrayOutputStream bil = new ByteArrayOutputStream();
            picture = ImageIO.read(fil);//datorn.createScreenCapture(new Rectangle(0, 0, 500, 500));

            ImageIO.write(picture, "PNG", bil);
            byte[] storlek = ByteBuffer.allocate(4).putInt(bil.size()).array();

            out.write(storlek);
            out.write(bil.toByteArray());
            out.flush();
            /*
            bil = ImageIO.createImageInputStream(picture);
            //bil.read(buffer, 0, buffer.length);
            ImageOutputStream bil = null;

            ImageIO.write(picture, "png", bil);
            buffer = bil.*/

        }catch(Exception e)
        {
            System.out.print("gg wr");
            e.printStackTrace();
        }

    }

}

错误有点不同

错误

conectadgg wp javax.imageio.IIOException: Error reading PNG image data
    at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.readImage(Unknown Source)
    at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.read(Unknown Source)
    at java.desktop/javax.imageio.ImageIO.read(Unknown Source)
    at java.desktop/javax.imageio.ImageIO.read(Unknown Source)
    at lärning5.Server.main(Server.java:134)
Caused by: javax.imageio.IIOException: Unknown row filter type (= 148)!
    at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.decodePass(Unknown Source)
    at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.decodeImage(Unknown Source)
    ... 5 more

我希望服务器能够顺利启动而不会出现任何错误,并且客户端能够顺利运行而不会出现任何错误。

但是当他们连接时,我希望服务器接收字节数组,但随后弹出错误仍在运行但什么也不做。您应该仍然可以按“s”,这将打开一个空白窗口。但这是错误的。

我真正想要发生的是服务器接收到字节数组,然后等待你按“s”,当你按“s”时,应该会弹出一个窗口显示接收到的图像。

如果我只是更改为“更小”(小于 22 mb)的图片,这实际上会发生。

【问题讨论】:

  • 我知道代码中有一些不必要或草率的细节,但我希望这不会打扰您
  • 我现在已经编辑了它,所以它是更多(如果不是)英文

标签: java image swing sockets jframe


【解决方案1】:

认为你的问题从这里开始:

in.read(buffer, 0, buffer.length)

当您为该方法求助 javadoc 时,它会说:

返回读入缓冲区的总字节数,如果由于已到达流的末尾而没有更多数据,则返回 -1。

绝对必须检查返回的“读取的字节数”。 99% 的时间,你会得到你想要的所有字节。但有时……比这还少!在这种情况下,您的缓冲区数组中的有效字节数将少于预期。

在您的情况下,您必须告诉服务器应该总共读取多少字节,然后您必须读取直到您真正准确读取该字节数!

长话短说:它从一个概念问题开始。单次读取缓冲区不足以处理可变大小的数据!您的服务器只有

byte[] buffer = new byte[899999];

但最有可能的是,您的客户端会发送不同的字节数。服务器应该如何知道确切将通过网络传输多少字节?!

所以:更改您的“协议”以首先告诉服务器将遵循多少字节。然后确保准确地读取那个数量的字节!这可能包括某种循环(当图像大于您的缓冲区数组时!)

【讨论】:

  • 我已经尝试过使用其他代码,但没有解决问题。但是无论如何我使缓冲区比需要的更大,它仍然不适用于大约 22mb 以上的图片
  • @MohmadMahra 然后更新您的输入并向我们展示您现在正在使用的确切代码。再次:您现在拥有的代码在概念上无法工作。你会“但我还写了一些其他代码”......不会改变任何东西。更糟糕的是:我们无法为您提供您未在问题中输入的代码。
  • 我更新了它。错误有点不同
  • @MohmadMahra 您的其他代码存在不同问题。抱歉,但您必须了解:这是一个问答网站。你问一个特定的问题,然后你会得到答案。这不是一项免费的辅导服务,人们可以与您坐下来帮助您解决在项目中遇到的不同问题。我给你的建议:把你的问题分解成更小的部分。首先从图像读取字节到缓冲区。并回到一个文件。确保您正确地执行此操作(通过将初始文件与您创建的副本进行比较)。以此类推。
  • 你看,你的第二个代码仍然完全错误。使用两个缓冲区没有帮助。您必须执行int bytesRead = in.read(...) 之类的操作,然后使用该数字bytesRead 以确保最终获得所需的确切字节数。但如前所述:这不是人们你如何做事的免费家教服务。我们给你一个提示,并指出相关的材料。
猜你喜欢
  • 1970-01-01
  • 2012-04-06
  • 2013-12-31
  • 1970-01-01
  • 2015-07-19
  • 2011-04-11
  • 1970-01-01
相关资源
最近更新 更多