2012-08-22 47 views
0

我在我的Android手机上创建一个程序,将相机的输出发送到同一网络上的服务器。这是我的Java代码:如何保持TCP数据包不被丢弃?

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)的。我对网络编程知之甚少,但我确实知道应该有足够的带宽。每张图像在18 fps时为640x480x1.5,约为63 Mbps。本地网络应该很容易处理,但我的Android调试器给了我很多“连接被拒绝”的消息。

任何帮助解决我的不良网络做法将是伟大的。 (我会稍微进行图像压缩 - 但现在我需要优化这一步)。

+4

为什么你一直打开和关闭TCP连接? –

+0

学会玩弄? – Dave

+0

这里没有证据表明TCP数据包完全被丢弃,'连接被拒绝'与带宽或丢包没有任何关系。您的代码在将任何文件写入文件之前将接收到的图像毫无意义地累积在内存中,这会浪费时间和空间。 – EJP

回答

5

您所设计的系统,使得它必须做很多次更多的工作比它应该这样做。您需要建立连接并拆除每个传输的帧。这不仅会导致吞吐量下降,而且还会让您失去资源。

通过合理的设计,传输帧所需的一切就是发送和接收帧数据。根据您的设计,对于每个帧,必须建立TCP连接(3个步骤),必须发送和接收帧数据,并且TCP连接必须被拆除。更糟的是,接收器无法知道它已收到所有的帧数据,直到发生连接关闭。所以这不能隐藏在后台。

设计一个合理的协议,问题就会消失。

+0

好吧,如果我通过一个TCP连接有稳定的图像数据流,那么就吞吐量而言,我能做到最好吗?还是有某种网络分析(MTU优化?),我应该执行?感谢您的好方法。 – Nick

+0

你需要一些标题,这样读者才能知道它有一个完整的框架。我建议将头文件和帧数据组合成单个缓冲区,以便您可以通过一次调用将其发送到'write'。在服务器中,你需要循环调用read,直到你有一个完整的框架。你可以循环直到你读完一个完整的头文件,然后循环,直到你读完整帧数据(小心不要过度读取),然后继续读取处理该帧后的下一个头文件。你必须在写作中积极主动,否则你可能会导致糟糕的Nagling /推迟ack。接收器中没有这样的问题。 –

+1

+1,因为@DavidSchwartz就在这里。使用TCP连接/断开进行消息成帧只是可以想象的最糟糕的协议,对于视频等需求尤其是高延迟无线网络的需求来说是完全可怕的。你现在需要一个合理的协议! –

1

这样工作吗?我没有看到你绑定到服务器端口3000的位置。

在任何情况下,如果这是一个视频流,您应该使用UDP而不是TCP。在UDP中,数据包可能会丢失,但对于视频流,这可能不会引起注意。由于交换的消息数量多,UDP通信所需的开销比TCP少得多。 TCP包含很多“确认”以确保每条数据到达目的地; UDP不关心,因此发送较少的数据包。根据我的经验,基于UDP的代码通常不比基于TCP的代码复杂。

_ryan

+0

是的,它的工作原理。我忽略了与问题无关的部分代码和修改的位。我会阅读UDP并给它一个镜头。有什么我应该知道的最大化吞吐量与UDP? (我知道我可能需要重新排序分组,并且处理在另一端下降的。) – Nick

+1

UDP利用被称为最大传输单元(MTU)这就通常〜1500个字节的标准以太网帧的大小。如果你可以压缩视频,使得帧这个尺寸范围内,你可以在这里你从一端扔包,赶上他们在其他,而无需丢弃的数据包或重新排序或任何其他不必要的复杂性方面有一个非常简单的协议。使用UDP,单个读取操作可以读取整个以太网帧的大小MTU,从而导致更小,更简单的代码和更好的性能。 – ryan0