java 通过套接字发送图像
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12242033/
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
Sending image over Socket
提问by Takami
i have a small problem sending image over Socket(client-server), i receive only "UTF" text but not the image object, is there something wrong with code?,
我在通过 Socket(客户端-服务器)发送图像时遇到一个小问题,我只收到“UTF”文本而不是图像对象,代码有问题吗?,
This code just sends the UTF txt and it's received on server side, i'm using the UTF text to identify an image(name) on server side and after identified it can send the image Object to client
此代码仅发送 UTF txt 并在服务器端接收,我使用 UTF 文本在服务器端识别图像(名称),识别后它可以将图像对象发送到客户端
/*
* ServerSide
*
*/
package Interface_class;
import configuraciones.procesador;
import java.awt.image.BufferedImage;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import javax.imageio.ImageIO;
/**
*
* @author TheCoder
*/
public class img_monitor extends Thread{
ServerSocket serverSocket;
Socket server;
BufferedImage bimg;
byte[] bytes;
public img_monitor()
{
try{
//Opening server socket
serverSocket = new ServerSocket(6066);
System.out.println("Conectado al Socket!");
}
catch(IOException ex){
System.out.println("Error en: "+ex);
}
}
public void run()
{
//This class gets the path from a property file (works well)
procesador obj = new procesador();
obj.UBARCHIVO_CONFIG();
while(true)
{
try
{
server = serverSocket.accept();
System.out.println("Nuevo cliente conectado!");
DataInputStream din=new DataInputStream(server.getInputStream());
DataOutputStream dout=new DataOutputStream(server.getOutputStream());
//Receiving image "name" from client as txt
String nombre = din.readUTF();
System.out.println(nombre);
//Using path+name of image to identify and send over socket
bimg = ImageIO.read(new File(obj.getRuta_arch_img()+nombre));
System.out.println(obj.getRuta_arch_img()+nombre);
ImageIO.write(bimg,"JPG",dout);
System.out.println("Image sent!!!");
// server.close();
//lblimg.setIcon(img);
}
catch(IOException e)
{
e.printStackTrace();
break;
}
catch(Exception ex)
{
System.out.println(ex);
}
}
}
}
Client Side
客户端
/*
* Client Side
*
*/
package Interface_class;
import java.awt.image.BufferedImage;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import javax.imageio.ImageIO;
/**
*
* @author TheCoder
*/
public class Obtener_imagen extends Thread {
public Obtener_imagen() {
System.out.println("Loading Socket!");
}
public void run() {
//The class below gets info from database
CLIENTINFO_CLASS obj = new CLIENTINFO_CLASS();
obj.consulta();
try {
Socket socket = new Socket("localhost", 6066);
// DataInputStream din = new DataInputStream(socket.getInputStream());
DataOutputStream dout = new DataOutputStream(socket.getOutputStream());
//Using this to send image "name" to server, so it can identify and send image to client
dout.writeUTF(obj.getImg_name());
BufferedImage img = ImageIO.read(ImageIO.createImageInputStream(socket.getInputStream()));
System.out.println("Image received!!!!");
// socket.close();
} catch (IOException ex) {
System.out.println("Error al abrir el socket" + ex);
}
}
}
采纳答案by user207421
You aren't closing the socket after you send the image, so the client never stops reading. The server should close the socket output stream, and close the socket itself in a finally block.
发送图像后您不会关闭套接字,因此客户端永远不会停止读取。服务器应该关闭套接字输出流,并在 finally 块中关闭套接字本身。
The client should also close his socket, in a finally block.
客户端还应该在 finally 块中关闭他的套接字。
EDIT:You don't need to use ImageIO to read and write the image files at the server, unless you are, say, changing the format. Just copy the bytes.
编辑:您不需要使用 ImageIO 在服务器上读取和写入图像文件,除非您要更改格式。只需复制字节。
回答by Dangling Piyush
Following code i have wriiten a few days ago working for any kind of file/text (UI Support).Hope you can find it useful for solving your problem.In this example you server starts listening of specified port and Multiple clients can send data after server is started.
以下代码是我几天前编写的,适用于任何类型的文件/文本(UI 支持)。希望您能发现它对解决您的问题很有用。在此示例中,您的服务器开始侦听指定端口,多个客户端可以在之后发送数据服务器启动。
/**
Client sends the data
**/
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Client extends JFrame
{
JFileChooser fc;
JButton browse;
JPanel p1;
private File file;
JButton upload;
private final int SERVER_PORT=5000;
private JTextField tf1;
BufferedInputStream bis;
BufferedOutputStream bos;
PrintWriter pw;
BufferedReader br;
public Client()
{
initGui();
}
public void initGui()
{
setSize(300,200);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
browse=new JButton("browse");
browse.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
open();
tf1.setText(file.getName());
}
});
tf1=new JTextField();
upload=new JButton("upload");
upload.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
try {
sendFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
add(tf1,BorderLayout.NORTH);
p1=new JPanel();
p1.setLayout(new FlowLayout(10,10,10));
p1.add(browse);
p1.add(upload);
add(p1,BorderLayout.SOUTH);
setVisible(true);
}
public void open()
{
fc = new JFileChooser();
fc.showOpenDialog(this);
file = fc.getSelectedFile();
try {
initNet();
} catch (Exception e) {
System.out.println("in initcatch");// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void initNet() throws Exception
{
Socket s=null;
try{
setTitle("Startd Client");
s=new Socket("localhost",SERVER_PORT);
bis=new BufferedInputStream(new FileInputStream(file));
bos=new BufferedOutputStream(s.getOutputStream());
pw=new PrintWriter(s.getOutputStream(),true);
br=new BufferedReader(new InputStreamReader(s.getInputStream()));
}catch(Exception e)
{
System.out.println("Error "+e);
}finally{
}
}
public void sendFile() throws IOException
{
pw.println(file.getName());
int ch=bis.read();
int counter=0;
pw.println(file.length());
while(counter<file.length())
{
bos.write(ch);
System.out.println(ch);
ch=bis.read();
counter++;
}
System.out.println(ch);
bos.write(ch);
bos.flush();
JOptionPane.showMessageDialog(null,br.readLine());
}
public static void main(String[] args) {
try{
Client c=new Client();
}catch(Exception e)
{
System.out.println("in catch");
}
}
}
And the server:
和服务器:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.PrintWriter;
import java.net.*;
import java.util.ArrayList;
import java.util.Scanner;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class Server extends JFrame
{
private JButton start;
private final int SERVER_PORT=5000;
private ArrayList<Thread> thrdList;
ServerSocket ss;
Socket s;
FileOutputStream fout;
BufferedInputStream bis;
BufferedReader br;
Scanner sc;
public Server()
{
initGui();
}
private void initGui()
{
setTitle("Server....");
setSize(300,200);
setResizable(false);
start=new JButton("start");
start.setBounds(10,20,20,20);
start.addActionListener(new ActionListener() {
public void actionPerformed( ActionEvent e )
{
try {
initNet();
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
);
add(start,BorderLayout.SOUTH);
setVisible(true);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent arg0) {
// TODO Auto-generated method stub
// super.windowClosing(arg0);
JOptionPane.showMessageDialog(null,"closed");
try{
if(br!=null)
br.close();
if(bis!=null)
br.close();
System.exit(0);
}catch(Exception e)
{
System.out.println("in cathch");
}
}
});
}
public void initNet() throws Exception
{
thrdList=new ArrayList<Thread>();
try{
while(true)
{
ss=new ServerSocket(SERVER_PORT,1);
while(true){
setTitle("Waitng for Client");
s=ss.accept();
MultiHandler mh=new MultiHandler(s);
thrdList.add(mh);
}
}
}catch(Exception e)
{
System.out.println("Error in initNEt"+e);
}finally{
for(Thread t:thrdList)
t.join();
if(ss!=null)
ss.close();
}
}
class MultiHandler extends Thread
{
Socket sock;
public MultiHandler(Socket s1) throws Exception
{
sock=s1;
br=new BufferedReader(new InputStreamReader(s.getInputStream()));
bis=new BufferedInputStream(s.getInputStream());
System.out.println("Stream attached");
start();
}
@Override
public void run()
{
try {
ClntHandler c=new ClntHandler(br,bis);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ClntHandler extends Thread
{
BufferedReader br1;
BufferedInputStream bis1;
String filename;
FileOutputStream fout;
public ClntHandler(BufferedReader in,BufferedInputStream bis) throws Exception
{
br1=in;
bis1=bis;
System.out.println("in clnthandler constr");
start();
}
@Override
public void run()
{
try{
filename=br1.readLine();
System.out.println(filename);
fout=new FileOutputStream(filename);
sc=new Scanner(s.getInputStream());
int size=sc.nextInt();
System.out.println("file created");
int ch=bis.read();
System.out.println(ch);
System.out.println("after bis.read()");
while(size>0)
{
fout.write(ch);
System.out.println(ch);
ch=bis1.read();
size--;
}
System.out.println(ch);
System.out.println("data written");
PrintWriter pw1=new PrintWriter(s.getOutputStream(),true);
pw1.println("DATA UPLOADED SUCCESSFULLY");
}catch(Exception e)
{
System.out.println("Error"+e);
}finally{
if(fout!=null)
try {
fout.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("IN Finally");
}
}
}
public static void main(String[] args) {
Server s=new Server();
}
}
回答by RollingCog
There is no separator between the image name Unicode string and actual binary image data. So I'm guessing the receiver will try to convert the entire received stream to string in:
图像名称 Unicode 字符串和实际二进制图像数据之间没有分隔符。所以我猜接收者会尝试将整个接收到的流转换为字符串:
String nombre = din.readUTF();
You can send the image name as a binary buffer with a size prefix, so your stream will look like:
您可以将图像名称作为带有大小前缀的二进制缓冲区发送,因此您的流将如下所示:
[Number of bytes used for image name] [image name in binary] [image data]
[用于图像名称的字节数] [二进制图像名称] [图像数据]
Then read the first 4 bytes in X, read the next X bytes and convert to string for image name, read the rest for image data. Good Luck :)
然后读取X中的前4个字节,读取接下来的X个字节并转换为图像名称的字符串,读取其余的图像数据。祝你好运 :)