如何通过java中的套接字发送图像?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25086868/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to send images through sockets in java?
提问by enemy
I am writing a client-server program and I want that to send an image. The code is the following:
我正在编写一个客户端 - 服务器程序,我希望它发送一个图像。代码如下:
//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");
}
}
And the server:
和服务器:
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){
//
}
}
My problem is that the client receive the image only if I close the socket or the out stream, but I don't want that to happen. How can I bypass that? How can I send the image as bytes? Thanks!
我的问题是只有当我关闭套接字或输出流时客户端才会收到图像,但我不希望这种情况发生。我怎样才能绕过它?如何将图像作为字节发送?谢谢!
回答by jakub.petr
The problem is that ImageIO.read waits for the end of the stream. Sockets send it only when you close it. (which makes sense)
问题是 ImageIO.read 等待流结束。套接字仅在您关闭它时发送它。(这是有道理的)
What you want to do is to first send size of the image and on the receiver side to read the image as byte array.
您要做的是首先发送图像的大小,然后在接收方将图像作为字节数组读取。
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();
}
}
回答by user2707001
You can find a (non-compiling) example at easywayprogramming.
您可以在easywayprogramming找到一个(非编译)示例。
I have simplified it and fixed the errors, I hope that this is a useful answer to your question.
我已经对其进行了简化并修复了错误,我希望这是对您问题的有用答案。
Run the server first, then run the client as often as you want.
首先运行服务器,然后根据需要运行客户端。
The example will take a screenshot of the upper left 200x100 pixels of your screen, send them to the server which will open a new window and display the screenshot.
该示例将截取屏幕左上角 200x100 像素的屏幕截图,将它们发送到服务器,服务器将打开一个新窗口并显示屏幕截图。
GreetingServer.java
问候服务器.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
问候客户.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();
}
}
}