Как отправить изображения через сокеты в 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();
}
}
}