Как отправить изображения через сокеты в Java?

Я пишу клиент-серверную программу и хочу чтобы изображение было отправлено. Код следующий:

//RECEIVER
while(true){
  try{
            socket = server.accept();

            out = new ObjectOutputStream(socket.getOutputStream());
            out.flush();
            in = new ObjectInputStream(socket.getInputStream());

            System.out.println("Connected to "+PORTA+".");

            while(!socket.isClosed()){ 
                System.out.println("\nPrint the action");
                azione = reader.readLine();

           if(azione.equals("screenshot")){

                    out.writeObject("screenshot");
                    out.flush();
                    BufferedImage screenshot = ImageIO.read(in);

                    ImageIO.write(screenshot, "jpg", new File("screenshot.jpg"));
                }
  }catch(Exception ex){
            System.out.println("Not connected.\n");
  } 
}

И сервер:

while(true){ 
   try{
            socket = new Socket(INDIRIZZO, PORT);

            out = new ObjectOutputStream(socket.getOutputStream());
            out.flush();
            in = new ObjectInputStream(socket.getInputStream());

            while(!socket.isClosed()){
                try {
                  action = (String)in.readObject();
                  if(azione.equals("screenshot")){
                        BufferedImage screenshot = new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
                        ImageIO.write(screenshot, "jpg", out);
                    }catch(Exception e){

                    }
            }
   }catch(Exception ex){
      //
   }
}

Моя проблема в том, что клиент получает изображение, только если я закрываю сокет или выходной поток, но я не хочу, чтобы это произошло. Как я могу обойти это? Как я могу отправить изображение в байтах? Спасибо!

2 ответа

Проблема в том, что ImageIO.read ожидает окончания потока. Сокеты отправляют только тогда, когда вы закрываете его. (что имеет смысл)

Что вы хотите сделать, это сначала отправить размер изображения и на стороне получателя, чтобы прочитать изображение в виде байтового массива.

public class Send {

    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("localhost", 13085);
        OutputStream outputStream = socket.getOutputStream();

        BufferedImage image = ImageIO.read(new File("C:\\Users\\Jakub\\Pictures\\test.jpg"));

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ImageIO.write(image, "jpg", byteArrayOutputStream);

        byte[] size = ByteBuffer.allocate(4).putInt(byteArrayOutputStream.size()).array();
        outputStream.write(size);
        outputStream.write(byteArrayOutputStream.toByteArray());
        outputStream.flush();
        System.out.println("Flushed: " + System.currentTimeMillis());

        Thread.sleep(120000);
        System.out.println("Closing: " + System.currentTimeMillis());
        socket.close();
    }
}


public class Receive {

    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(13085);
        Socket socket = serverSocket.accept();
        InputStream inputStream = socket.getInputStream();

        System.out.println("Reading: " + System.currentTimeMillis());

        byte[] sizeAr = new byte[4];
        inputStream.read(sizeAr);
        int size = ByteBuffer.wrap(sizeAr).asIntBuffer().get();

        byte[] imageAr = new byte[size];
        inputStream.read(imageAr);

        BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageAr));

        System.out.println("Received " + image.getHeight() + "x" + image.getWidth() + ": " + System.currentTimeMillis());
        ImageIO.write(image, "jpg", new File("C:\\Users\\Jakub\\Pictures\\test2.jpg"));

        serverSocket.close();
    }

}

Вы можете найти ( некомпилируемый) пример в easywayprogramming.

Я упростил и исправил ошибки, надеюсь, что это полезный ответ на ваш вопрос.

Сначала запустите сервер, затем запустите клиент так часто, как вы хотите.

В примере будет сделан снимок экрана с верхним левым размером 200x100 пикселей вашего экрана, он будет отправлен на сервер, который откроет новое окно и отобразит снимок экрана.

GreetingServer.java

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.sql.SQLException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class GreetingServer extends Thread
{
       private ServerSocket serverSocket;
       Socket server;

       public GreetingServer(int port) throws IOException, SQLException, ClassNotFoundException, Exception
       {
          serverSocket = new ServerSocket(port);
          serverSocket.setSoTimeout(180000);
       }

       public void run()
       {
           while(true)
          { 
               try
               {
                  server = serverSocket.accept();
                  BufferedImage img=ImageIO.read(ImageIO.createImageInputStream(server.getInputStream()));
                  JFrame frame = new JFrame();
                  frame.getContentPane().add(new JLabel(new ImageIcon(img)));
                  frame.pack();
                  frame.setVisible(true);                  
              }
             catch(SocketTimeoutException st)
             {
                   System.out.println("Socket timed out!");
                  break;
             }
             catch(IOException e)
             {
                  e.printStackTrace();
                  break;
             }
             catch(Exception ex)
            {
                  System.out.println(ex);
            }
          }
       }

       public static void main(String [] args) throws IOException, SQLException, ClassNotFoundException, Exception
       {
              Thread t = new GreetingServer(6066);
              t.start();
       }
}

GreetingClient.java

import java.awt.AWTException;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.Socket;

import javax.imageio.ImageIO;

public class GreetingClient
{
    Image newimg;
    static BufferedImage bimg;
    byte[] bytes;

    public static void main(String [] args)
    {
        String serverName = "localhost";
        int port = 6066;
        try
        {
            Socket client = new Socket(serverName, port);
            Robot bot;
            bot = new Robot();
            bimg = bot.createScreenCapture(new Rectangle(0, 0, 200, 100));
            ImageIO.write(bimg,"JPG",client.getOutputStream());
            client.close();
        } catch(IOException | AWTException e) {
            e.printStackTrace();
        }
    }
}
Другие вопросы по тегам