You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#转Java实现IP摄像头TCP收发指令、UDP接收图片问题求助

问题排查与修正方案

核心错误点

  • 指令码不匹配:C#原代码触发取图的指令首字节为20,现有Java代码误写为22,摄像头无法识别取图请求
  • 响应解析逻辑错误:C#的报文长度编码为4字节大端序整数,现有Java代码用getShort()仅读取2字节,无法正确解析响应长度
  • 图片端口逻辑缺失:现有代码仅创建了8501端口的连接,未实现从该端口读取图片数据的逻辑
  • 连接关闭时机错误:未完成图片数据读取就提前关闭所有连接,导致传输中断

修正后实现代码

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;

public class TFinale {
    static byte[] DataReceived = new byte[20000];
    private static final String CAMERA_IP = "10.0.0.123";
    private static final int COMMAND_PORT = 8500;
    private static final int VIDEO_PORT = 8501;

    public static void main(String[] args) {
        Socket commandSocket = null;
        Socket videoSocket = null;
        DataOutputStream commandOut = null;
        DataInputStream commandIn = null;
        DataInputStream videoIn = null;

        try {
            // 建立两个端口的连接
            commandSocket = createSocket(CAMERA_IP, COMMAND_PORT);
            videoSocket = createSocket(CAMERA_IP, VIDEO_PORT);
            if (commandSocket == null || videoSocket == null) {
                System.err.println("端口连接失败");
                return;
            }

            // 构造发送指令 注意首字节是20不是22
            byte[] sendCmd = new byte[3];
            sendCmd[0] = 20;    //CMD BAR CODE READER
            sendCmd[1] = 2;    //EXT CMD GET DATA
            sendCmd[2] = 2;    //SEND IMAGE
            byte[] sendPacket = SendEth(sendCmd, 3);

            // 发送指令到命令端口
            commandOut = new DataOutputStream(commandSocket.getOutputStream());
            commandOut.write(sendPacket);
            commandOut.flush();
            System.out.println("取图指令已发送");

            // 读取命令端口响应
            commandIn = new DataInputStream(commandSocket.getInputStream());
            // 先读4字节长度
            byte[] lenBytes = new byte[4];
            commandIn.readFully(lenBytes);
            int respLen = ByteBuffer.wrap(lenBytes).getInt();
            // 读剩余响应内容
            byte[] respContent = new byte[respLen];
            commandIn.readFully(respContent);
            // 校验响应指令
            if (respContent[0] != 20) {
                System.err.println("指令响应错误");
                return;
            }
            System.out.println("指令响应校验通过,开始读取图片");

            // 从视频端口读取图片数据
            videoIn = new DataInputStream(videoSocket.getInputStream());
            // 先读4字节图片长度(和C#逻辑对应)
            byte[] imgLenBytes = new byte[4];
            videoIn.readFully(imgLenBytes);
            int imgLen = ByteBuffer.wrap(imgLenBytes).getInt();
            // 读取完整图片字节
            byte[] imgBytes = new byte[imgLen];
            videoIn.readFully(imgBytes);

            // 转成图片保存
            ByteArrayInputStream bais = new ByteArrayInputStream(imgBytes);
            BufferedImage image = ImageIO.read(bais);
            ImageIO.write(image, "jpg", new File("camera_capture.jpg"));
            System.out.println("图片已保存到camera_capture.jpg");

        } catch (Exception e) {
            Logger.getLogger(TFinale.class.getName()).log(Level.SEVERE, null, e);
        } finally {
            // 最后再关闭所有资源
            try {
                if (commandOut != null) commandOut.close();
                if (commandIn != null) commandIn.close();
                if (videoIn != null) videoIn.close();
                if (commandSocket != null) commandSocket.close();
                if (videoSocket != null) videoSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static Socket createSocket(final String hostname, final int port) {
        try {
            Socket clientSocket = new Socket(hostname, port);
            clientSocket.setSoTimeout(10000); // 设置10秒超时
            System.out.println(hostname + ":" + port + " 连接成功");
            return clientSocket;
        } catch (Exception e) {
            System.err.println(hostname + ":" + port + " 连接失败: " + e.getMessage());
            return null;
        }
    }

    private static byte[] SendEth(byte[] _Val, int _Len) {
        byte[] _Send = new byte[_Len + 4];
        int _Value = _Len;
        System.arraycopy(_Val, 0, _Send, 4, _Len);
        _Send[3] = (byte) _Value;
        _Value <<= 8;
        _Send[2] = (byte) _Value;
        _Value <<= 8;
        _Send[1] = (byte) _Value;
        _Value <<= 8;
        _Send[0] = (byte) _Value;
        return _Send;
    }
}

补充说明

如果确认8501端口为UDP传输,将视频端口的Socket替换为DatagramSocket实现即可,注意UDP是无连接协议,需要先绑定本地端口再接收数据包。

内容的提问来源于stack exchange,提问作者Federico111

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 04:15:03