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
相关产品推荐
相关产品推荐

