Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在java中通过套接字发送屏幕截图(BuffereImage)_Java_Sockets_Bufferedimage - Fatal编程技术网

在java中通过套接字发送屏幕截图(BuffereImage)

在java中通过套接字发送屏幕截图(BuffereImage),java,sockets,bufferedimage,Java,Sockets,Bufferedimage,我正在通过套接字发送BuffereImage,并使用post中的示例: 寄件人 BufferedImage image = ....; ImageIO.write(image, "PNG", socket.getOutputStream()); 接受者 BufferedImage image = ImageIO.read(socket.getInputStream()); 它可以工作-如果且仅当我在此行后关闭发件人的outputStream: ImageIO.write(

我正在通过套接字发送BuffereImage,并使用post中的示例:

寄件人

   BufferedImage image = ....;
   ImageIO.write(image, "PNG", socket.getOutputStream());
接受者

   BufferedImage image = ImageIO.read(socket.getInputStream());
它可以工作-如果且仅当我在此行后关闭发件人的outputStream:

 ImageIO.write(image, "PNG", socket.getOutputStream());
除了关闭outputStream,我还能做什么

另外,我还能做些什么来避免完全使用ImageIO吗?做任何事似乎都要花很长时间。 还请注意,由于性能问题,无论如何都应避免读取或写入硬盘。我需要尽可能快地进行传输,(我正在试验并尝试创建一个类似于VNC的客户端,并将每个屏幕截图保存到硬盘将大大降低速度)

@乔恩·斯基特

编辑3:

发件人:(注意,我发送的是JPG图像,不是PNG)

(失败:getWidth()行上出现空指针异常) 我理解这个错误的意思是“损坏的图像”,因为它无法初始化它。对吗

尝试#2:

接受者:

    InputStream in = clientSocket.getInputStream();
    long startTime = System.currentTimeMillis();

    byte[] b = new byte[30];
    int len = in.read(b);

    int filesize = Integer.parseInt(new String(b).substring(0, len));

    if (filesize > 0)
    {
        byte[] imgBytes = readExactly(in, filesize);
        FileOutputStream f = new FileOutputStream("C:\\Users\\Dan\\Desktop\\Pic\\1.jpg");
        f.write(imgBytes);
        f.close();

        System.out.println("done");
发送方仍然提供由对等方重置的连接:套接字写入错误。

一个选项是通过tearrayoutputstream将图像写入
以便确定长度,然后首先将该长度写入输出流

然后在接收端,您可以读取长度,然后将那么多字节读入字节数组,然后创建一个
ByteArrayInputStream
来包装数组并将其传递给
ImageIO.read()

我并不完全感到惊讶,直到输出套接字正常关闭,它才工作——毕竟,一个包含有效PNG文件的文件,然后其他文件本身实际上不是有效的PNG文件,是吗?因此,读取器需要读取到流的结尾,然后才能完成,而网络流的“结尾”只有在连接关闭时才会出现

编辑:这里有一种方法可以将给定数量的字节读入新的字节数组。它作为一个单独的“实用”方法很方便

public static byte[]readjuckly(InputStream输入,int size)引发IOException
{
字节[]数据=新字节[大小];
int指数=0;
while(索引<大小)
{
int bytesRead=input.read(数据、索引、大小-索引);
如果(字节读取<0)
{
抛出新IOException(“流中数据不足”);
}
指数+=大小;
}
返回数据;
}

适用于像我这样的其他StackOverflow用户

在“Jon Skeet”的回答中。修改readjustice方法的以下行

    <<original Line>>
    index += size;
    <<modified Line>>
    index += bytesRead;

指数+=大小;
索引+=字节读取;
获取完整的图像数据

public static void main(String[] args) {
    Socket socket = null;
    try {
        DataInputStream dis;
        socket = new Socket("192.168.1.48",8000);
        while (true) {
            dis = new DataInputStream(socket.getInputStream());
            int len = dis.readInt();
            byte[] buffer = new byte[len];
            dis.readFully(buffer, 0, len);
            BufferedImage im = ImageIO.read(new ByteArrayInputStream(buffer));
            jlb.setIcon(new ImageIcon(im));
            jfr.add(jlb);
            jfr.pack();
            jfr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            jfr.setVisible(true);
            System.gc();
        }
    } catch (Exception e) {
        e.printStackTrace();
    } 
    finally {
        try {
            socket.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

在192.168.1.48:8000机器python服务器运行时,我得到了java代码流

@David:这是非常复杂的代码-特别是,您永远不应该捕捉到ArrayIndexOutOfBoundsException。为什么不直接使用out.write(imgByte)
?在接收端,您使用的是
client.getInputStream().read(缓冲区)
完全忽略
read
的返回值。这不是个好主意。调用
getInputStream()
一次,然后多次调用
read
,记录每次调用读取的数据量。不要假设它将始终与接收大小相同。是的,我忘了提及。write(imgByte)以某种方式立即强制套接字关闭,并断开客户端的连接。我不明白为什么会发生这种情况,但我认为一次可以写入的数据量一定是有限制的,所以我尝试将其拆分并发送出去。@David:不,将数据写入套接字应该是绝对正确的。你确定不是接收方关闭了套接字吗?@David:你仍然忽略了
input.read()
的返回值。你不能那样做。您需要循环,计算出仍需要读取的数据量,并一次读取一个数据块。通过网络连接,你不可能一次就得到所有的信息。只是做了一次——编辑尝试4。接收者没有给出任何错误。然而,当我试图一次写入超过200kb的输出流时,发送方只是断开连接并说“由对等方重置连接”。有什么想法吗?
if (filesize > 0)
{

    int writtenBytes = 0;
    int bufferSize = client.getReceiveBufferSize();

    imageBytes = new byte[filesize];     //Create a byte array as large as the image
    byte[] buffer = new byte[bufferSize];//Create buffer


    do {
        writtenBytes += input.read(buffer); //Fill up buffer
        System.out.println(writtenBytes + "/" + filesize); //Show progress

        //Copy buffer to the byte array which will contain the full image
        System.arraycopy(buffer, 0, imageBytes, writtenBytes, client.getReceiveBufferSize());
        writtenBytes+=bufferSize;

    } while ((writtenBytes + bufferSize) < filesize);

    // Read the remaining bytes
    System.arraycopy(buffer, 0, imageBytes, writtenBytes-1, filesize-writtenBytes);
    writtenBytes += filesize-writtenBytes;
    System.out.println("Finished reading! Total read: " + writtenBytes + "/" + filesize);

}

InputStream in = new ByteArrayInputStream(imageBytes);
BufferedImage image = ImageIO.read(in);
in.close();
   int readBytes = 0;
   imageBytes = new byte[filesize];     //Create a byte array as large as the image



    while (readBytes < filesize)
    {
        readBytes += input.read(imageBytes);
    }

    InputStream in = new ByteArrayInputStream(imageBytes);
    BufferedImage image = ImageIO.read(in);
    in.close();

    System.out.println("width=" + image.getWidth());
    Socket s = new Socket("127.0.0.1", 1290);
    OutputStream out = s.getOutputStream();

    ByteArrayOutputStream bScrn = new ByteArrayOutputStream();
    ImageIO.write(captureImg(), "JPG", bScrn);
    byte imgBytes[] = bScrn.toByteArray();
    bScrn.close();

    out.write((Integer.toString(imgBytes.length)).getBytes());
    out.write(imgBytes,0,imgBytes.length);
    InputStream in = clientSocket.getInputStream();
    long startTime = System.currentTimeMillis();

    byte[] b = new byte[30];
    int len = in.read(b);

    int filesize = Integer.parseInt(new String(b).substring(0, len));

    if (filesize > 0)
    {
        byte[] imgBytes = readExactly(in, filesize);
        FileOutputStream f = new FileOutputStream("C:\\Users\\Dan\\Desktop\\Pic\\1.jpg");
        f.write(imgBytes);
        f.close();

        System.out.println("done");
public static byte[] readExactly(InputStream input, int size) throws IOException
{
    byte[] data = new byte[size];
    int index = 0;
    while (index < size)
    {
        int bytesRead = input.read(data, index, size - index);
        if (bytesRead < 0)
        {
            throw new IOException("Insufficient data in stream");
        }
        index += size;
    }
    return data;
}
    <<original Line>>
    index += size;
    <<modified Line>>
    index += bytesRead;
public static void main(String[] args) {
    Socket socket = null;
    try {
        DataInputStream dis;
        socket = new Socket("192.168.1.48",8000);
        while (true) {
            dis = new DataInputStream(socket.getInputStream());
            int len = dis.readInt();
            byte[] buffer = new byte[len];
            dis.readFully(buffer, 0, len);
            BufferedImage im = ImageIO.read(new ByteArrayInputStream(buffer));
            jlb.setIcon(new ImageIcon(im));
            jfr.add(jlb);
            jfr.pack();
            jfr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            jfr.setVisible(true);
            System.gc();
        }
    } catch (Exception e) {
        e.printStackTrace();
    } 
    finally {
        try {
            socket.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}