我正在Android手机上创建一个程序,将相机的输出发送到同一网络上的服务器。这是我的Java代码:
camera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera cam) {
try {
socket = new Socket("XXX.XXX.XXX.XXX", 3000);
out = socket.getOutputStream();
out.write(data);
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
camera.addCallbackBuffer(data);
}
服务器是NodeJS服务器:
time = 0
video_server.on 'connection', (socket) ->
buffer = []
socket.on 'data', (data) ->
buffer.push data
socket.on 'end', ->
new_time = (new Date()).getTime()
fps = Math.round(1000/(new_time - time)*100)/100
console.log fps
time = new_time
stream = fs.createWriteStream 'image.jpg'
stream.on 'close', ->
console.log 'Image saved.', fps
stream.write data for data in buffer
stream.end()
我的终端显示大约1.5 fps(5 Mbps)。我对网络编程知之甚少,但我知道应该有足够的带宽。每个图像为640x480x1.5,18 fps,约为63 Mbps。本地网络应该能够轻松处理这个问题,但我在Android中的调试器给了我很多“拒绝连接”的消息。
任何有关修复错误网络实践的帮助都会很棒。 (我稍后会对图像进行压缩 - 但是现在我需要优化这一步骤。)
答案 0 :(得分:5)
您已经设计了系统,因此它必须完成比它应该做的工作多很多倍的工作。您需要为传输的每个帧建立和拆除连接。这不仅会扼杀您的吞吐量,还会让您失去资源。
使用理智的设计,传输帧所需的全部内容是发送和接收帧数据。根据您的设计,对于每个帧,必须建立TCP连接(3个步骤),必须发送和接收帧数据,并且必须拆除TCP连接。更糟糕的是,接收器无法知道它已经接收到所有帧数据,直到发生连接关闭。所以这不能隐藏在后台。
设计一个理智的协议,问题就会消失。
答案 1 :(得分:1)
这有用吗?我没有看到你在服务器上绑定到端口3000的位置。
在任何情况下,如果这是一个视频流,您可能应该使用UDP而不是TCP。在UDP中,可能会丢弃数据包,但对于视频流,这可能不会引人注意。由于交换的消息数量,UDP通信所需的开销要比TCP少得多。 TCP包含许多“确定”以确保每个数据到达目的地; UDP不关心,因此发送的数据包较少。根据我的经验,基于UDP的代码通常不如基于TCP的代码复杂。
_ryan