web-dev-qa-db-fra.com

Comment envoyer des images via des sockets en Java?

J'écris un programme client-serveur et je veux qu'il envoie une image. Le code est le suivant:

//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");
  } 
}

Et le serveur:

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){
      //
   }
}

Mon problème est que le client reçoit l'image uniquement si je ferme le socket ou le flux de sortie, mais je ne veux pas que cela se produise. Comment puis-je contourner cela? Comment envoyer l'image en octets? Merci!

7
enemy

Le problème est que ImageIO.read attend la fin du flux. Les sockets n'envoient que lorsque vous le fermez. (ce qui est logique)

Ce que vous voulez faire, c'est d'abord envoyer la taille de l'image et du côté récepteur pour lire l'image sous forme de tableau d'octets.

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

}
13
jakub.petr

Vous pouvez trouver un exemple (non compilateur) sur easywayprogramming .

Je l'ai simplifié et corrigé les erreurs, j'espère que c'est une réponse utile à votre question.

Exécutez d'abord le serveur, puis exécutez le client aussi souvent que vous le souhaitez.

L'exemple prendra une capture d'écran des 200x100 pixels en haut à gauche de votre écran, les enverra au serveur qui ouvrira une nouvelle fenêtre et affichera la capture d'écran.

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