【问题标题】:Multiple image files on a TCP socketTCP 套接字上的多个图像文件
【发布时间】:2014-04-30 10:19:21
【问题描述】:

我正在尝试在 TCP 套接字上发送多个图像。

以下代码运行良好,没有问题:客户端和服务器交换问候语。然后客户端正在发送 服务器接收的单个图像文件。

客户端:

...        
try      {
    Socket clientSocket = new Socket(serverName, port);
    DataInputStream in=new DataInputStream(clientSocket.getInputStream());
    System.out.println("Heard from server: "+in.readUTF());

    DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream());
    out.writeUTF("Hello from " + clientSocket.getLocalSocketAddress());

    BufferedImage bimg;

//    for (int i=0; i<3; i++)  {
    bimg = ImageIO.read(new File("flowers.jpg"));  
    ImageIO.write(bimg,"jpg",clientSocket.getOutputStream());   
    out.flush(); 
    System.out.println("Image sent");
//    }
    clientSocket.close();
  } catch(Exception e) { ... }

服务器端:

...
Socket socket=null;
DataInputStream din=null;
DataOutputStream dout=null;
...
socket = serverSocket.accept();  
din=new DataInputStream(socket.getInputStream());
dout=new DataOutputStream(socket.getOutputStream());

for (;;)  {  
    try  {

        dout.writeUTF("ImageReceiver here at your service: ");

        System.out.println("from the client: "+din.readUTF());
        BufferedImage img;

//for (int i=0; i<3; i++) {
        img=ImageIO.read(socket.getInputStream());   
        ImageIO.write(img, "png", new File(timeStamp+"img.png"));
        System.out.println("Image received...");
//} 
        socket.close();
        break;
   }
  catch(Exception e) {  .... }
 }

当我取消注释上面的 2*2 行并因此循环发送和接收图像时,我收到图像为空的异常:

服务器正在接收第一张图片,没有错误。然而,在那之后,它不是 将输入流视为图像。

处对 ImageIO.read() 的调用
img=ImageIO.read(socket.getInputStream());    

正在返回 null 并且

        ImageIO.write(img, "png", new File(timeStamp+"img.png"));

正在引发异常。

客户端进程运行良好,没有任何错误。

这是管理 I/O 缓冲区的问题吗?

去哪里修复它?

TIA。

//========================================

我在发送 2 张图片时遇到了同样的错误:第一张图片可以正常传输和接收。

客户端正在发送第二张图片作为关闭前的最后一件事。但是,服务器没有将第二个视为图像。在传输第一张图像后,服务器套接字的输入缓冲区中除了第二张图像之外什么都没有。

【问题讨论】:

  • 您不需要 ImageIO 来读取文件并通过套接字发送它,或者反之亦然。只需发送字节。
  • 我不确定,但ImageIO.read() 可能会一直读取到流的末尾或获取一些额外的数据。在这种情况下,您可以更改您的协议以首先将图像转换为byte[],发送数据长度和数据本身,然后在接收端仅将必要的数据读取到byte[] 并从中构造图像。这样ImageIO.read() 不会比你想要的多。不要引用我的话。如果我错了,请有人纠正我。
  • @EJP 如果您想利用将其编码为较小的图像格式(例如 PNG)进行传输,您会这样做。
  • @EJP 为什么上面的方法首先不起作用。我什至不知道问题出在哪里。
  • @JasonC:在 Q 中查看我的编辑。

标签: java sockets tcp inputstream javax.imageio


【解决方案1】:

ImageIO 读取图像后关闭输入流。需要通过 ImageIO.createImageInputStream() 反复创建读取多个图像。 可以看这里-https://docs.oracle.com/javase/8/docs/api/javax/imageio/ImageIO.html#read-javax.imageio.stream.ImageInputStream-

【讨论】:

    【解决方案2】:

    你可以试试这个代码。此代码以字节为单位发送数据。

    客户(发件人):

    try {
            int port = 8989; // Your Server port number
            Socket sender = new Socket("Server IP", port);
            int count,i=0;
    
            byte[] data = new byte[1024]; // Here provide size of your file
            FileInputStream fileStream = null;
            BufferedInputStream fileBuffer = null;
            OutputStream out = sender.getOutputStream();
            InputStream in = sender.getInputStream();
    
            while (i < 10) {
    
                fileStream = new FileInputStream("fileURL");
                fileBuffer = new BufferedInputStream(fileStream);
    
                // Sending file data in bytes
                while ((count = fileBuffer.read(data)) > 0) {
                    System.out.println("Data Sent : " + count);
                    out.write(data, 0, count);
                    out.flush();
                }
    
                // Waiting for response
                while (in.available() <= 0) {
                }
                if (in.read() == 0) {
                    System.out.println("File Sent Successfully");
                    i++;
                } else {
                    System.out.println("File Not Sent Successfully");
                }
            }
        } catch (Exception e) {
        }
    

    服务器(接收方):

    try {
            ServerSocket server = new ServerSocket(port);
    
            // Waiting for client
            Socket receiveSocket = server.accept();
            InputStream in = receiveSocket.getInputStream();
            OutputStream out = receiveSocket.getOutputStream();
            int count, cnt = 10, i = 0;
    
            // cnt will be total number of files
            while (i < cnt) {
                byte data[] = new byte[1024]; // Provide file size here
                FileOutputStream fileOut = new FileOutputStream("fileURL");
                BufferedOutputStream fileBuffer = new BufferedOutputStream(fileOut);
    
                // Waiting till client is sending the file
                while (in.available() <= 0) {
                }
                // Receiving byte data and storing it in the file
                while ((count = in.read(data)) > 0) {
                    fileBuffer.write(data, 0, count);
                    System.out.println("Data Received : " + count);
                    fileBuffer.flush();
                }
                // Notify client that you received that file successfully
                out.write(0);
    
                // Close all streams
                in.close();
                out.close();
                fileBuffer.close();
                fileOut.close();
                i++;
            }
        } catch (Exception e) {
        }
    

    希望对你有所帮助。

    【讨论】:

    • thx - 但希望对上述代码进行整理。已经有一个字节了。
    • 是的,但这也不会产生任何异常。这个我试过了。
    • 没有必要“在这里提供文件的大小”。 1024 或任何正值都适用于缓冲区大小。等待响应的available() 循环实际上是在浪费时间,也是对 CPU 的滥用。只需将其删除即可解决这两个问题。以下read() 将一直阻塞,直到数据到达为止。您还在发送之前打印“发送的数据”,也就是说至少会产生误导。不需要在图像之后发送另一个字节的应用程序协议。
    猜你喜欢
    • 2013-04-17
    • 2020-04-28
    • 2011-08-05
    • 2021-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-30
    相关资源
    最近更新 更多