2012-08-22 2 views
0

카메라 출력을 동일한 네트워크의 서버로 보내려면 Android 휴대 전화에 프로그램을 만들고 있습니다.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의)를 보여주고있다 여기 내 자바 코드입니다. 네트워크 프로그래밍에 대해서는 거의 알지 못하지만 대역폭이 충분해야합니다. 각 이미지는 18fps에서 640x480x1.5이며 약 63Mbps입니다. 로컬 네트워크에서이 문제를 쉽게 처리 할 수 ​​있어야하지만 안드로이드의 디버거는 "Connection refused"메시지를 많이 보내고 있습니다.

나쁜 네트워크 관행을 고치는 데 도움이 될 것입니다. (약간의 이미지 압축을 얻지 만, 지금은이 단계를 최적화해야합니다.)

+4

왜 TCP 연결을 열고 닫는 중입니까? –

+0

저글링을 배우십시오? – Dave

+0

여기에 TCP 패킷이 전혀 삭제되지 않는다는 증거는 없으며 '연결 거부 됨'은 대역폭 또는 삭제 된 패킷과 관련이 전혀 없습니다. 코드는 수신 된 이미지를 파일에 쓰기 전에 메모리에 누적없이 누적되어 시간과 공간을 낭비합니다. – EJP

답변

5

. 전송 된 각 프레임마다 연결이 끊어 지도록해야합니다. 이는 처리량을 떨어 뜨릴뿐만 아니라 리소스를 낭비 할 수도 있습니다.

정상적인 디자인을 사용하면 프레임을 전송하는 데 필요한 모든 것이 프레임 데이터를 보내고받는 것입니다. 디자인 할 때 각 프레임마다 TCP 연결을 구축해야하며 (3 단계) 프레임 데이터를 보내고 받아야하며 TCP 연결을 해체해야합니다. 더욱이 수신자는 연결 종료가 발생할 때까지 프레임 데이터를 모두 수신했다는 것을 알 수 없습니다. 그래서 이것은 백그라운드에서 감추어 질 수 없습니다.

정상적인 프로토콜을 설계하면 문제가 해결됩니다.

+0

하나의 TCP 연결을 통해 꾸준히 이미지 데이터를 전송할 수 있다면 처리량 측면에서 최선을 다할 것인가? 아니면 내가 수행해야하는 일종의 네트워크 분석 (MTU 최적화?)이 있습니까? 좋은 답변을 주셔서 감사합니다. – Nick

+0

독자가 완전한 프레임을 가지고있을 때 알 수 있도록 헤더가 필요합니다. 헤더와 프레임 데이터를 하나의 버퍼에 모아서'write'를 한 번 호출하면된다. 서버에서 전체 프레임을 얻을 때까지 루프 읽기를 반복해야합니다. 전체 헤더를 읽을 때까지 반복 할 수 있습니다. 그런 다음 전체 프레임 데이터를 읽을 때까지 반복하고 (과도하게 읽지 않도록주의하십시오.) 그런 다음 해당 프레임을 처리 한 후 다음 헤더를 읽으십시오. 그렇지 않으면 나쁜 Nagling/지연된 ack을 유발할 수 있기 때문에 글쓰기에 적극적이어야합니다. 수신기에 그러한 문제가 없습니다. –

+1

+1 @DavidSchwartz가 여기 있습니다. 메시지 - 프레이밍을 위해 TCP 연결/연결 해제를 사용하는 것은 비디오와 같은 요구 사항, 특히 대기 시간이 긴 무선 네트워크에서 상상할 수있는 최악의 프로토콜 일뿐입니다. 이제는 정상적인 프로토콜이 필요합니다! –

1

전혀 작동합니까? 서버의 포트 3000에 바인딩하는 위치가 표시되지 않습니다.

비디오 스트림 인 경우 TCP 대신 UDP를 사용해야합니다. UDP에서는 패킷이 삭제 될 수 있지만 비디오 스트림의 경우에는 눈에 띄지 않습니다. UDP 통신은 교환되는 메시지의 수 때문에 TCP보다 훨씬 적은 오버 헤드를 필요로합니다. TCP는 각 데이터 조각이 대상에 도달하도록하는 "acking"을 많이 포함하고 있습니다. UDP는 상관하지 않으므로 더 적은 패킷을 전송합니다. 내 경험상, UDP 기반 코드는 일반적으로 TCP 기반 코드보다 덜 복잡합니다.

_ryan

그것이이 할 수있는 것보다 훨씬 더 많은 일을해야한다 있도록 시스템을 설계 한
+0

예, 작동합니다. 나는 코드의 일부를 생략하고 질문과 관련이없는 부분을 수정했다. 나는 UDP를 읽고 그것을 알려줄 것이다. UDP로 처리량을 최대화하는 것에 대해 알아야 할 것이 있습니까? (나는 패킷을 재 순서화하고 다른 끝에 패킷을 다시 처리해야 할 필요가 있음을 알고 있습니다.) – Nick

+1

UDP는 최대 전송 단위 (MTU)로 알려진 표준 이더넷 프레임 크기를 사용하며, 일반적으로 ~ 1500 바이트입니다. 프레임이이 크기 내에 있도록 비디오를 압축 할 수 있으면 손실 된 패킷이나 재정렬 또는 기타 불필요한 복잡성에 관계없이 한 쪽 끝에서 패킷을 던져 다른 쪽 끝에서 잡는 아주 간단한 프로토콜을 사용할 수 있습니다. UDP를 사용하면 단일 읽기 작업으로 크기 MTU의 전체 이더넷 프레임을 읽을 수 있으므로 작고 단순한 코드와 성능이 향상됩니다. – ryan0

관련 문제