2012-06-12 2 views
1

파이썬 이미징 라이브러리로 이미지를 그리는 서버 측 함수가 있습니다. Java 클라이언트는 소켓을 통해 반환되고 BufferedImage로 변환 된 이미지를 요청합니다.자바 클라이언트와 Twisted Python 소켓 서버간에 버퍼링 된 이미지 보내기

전송할 이미지의 크기와 CR 다음에 데이터의 접두어를 붙입니다. 그런 다음 소켓 입력 스트림에서이 수의 바이트를 읽고 ImageIO를 사용하여 BufferedImage로 변환하려고 시도합니다.

public String writeAndReadSocket(String request) { 
    // Write text to the socket 
    BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); 
    bufferedWriter.write(request); 
    bufferedWriter.flush(); 

    // Read text from the socket 
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 

    // Read the prefixed size 
    int size = Integer.parseInt(bufferedReader.readLine()); 

    // Get that many bytes from the stream 
    char[] buf = new char[size]; 
    bufferedReader.read(buf, 0, size); 
    return new String(buf); 
} 

public BufferedImage stringToBufferedImage(String imageBytes) { 
    return ImageIO.read(new ByteArrayInputStream(s.getBytes())); 
} 

서버 : 축약 된 클라이언트에 대한 코드에서

이 문자열을 전송 및 수신을 위해 작동하지만, 이미지 변환 (일반적으로) 실패
# Twisted server code here 

# The analog of the following method is called with the proper client 
# request and the result is written to the socket. 
def worker_thread(): 
    img = draw_function() 
    buf = StringIO.StringIO() 
    img.save(buf, format="PNG") 
    img_string = buf.getvalue() 
    return "%i\r%s" % (sys.getsizeof(img_string), img_string) 

. 이미지가 제대로 읽히지 않는 이유를 이해하려고합니다. 가장 좋은 추측은 클라이언트가 적절한 바이트 수를 읽지 않는다는 것입니다. 그러나 솔직히 그것이 왜 그런지 알지 못합니다.

사이드 노트 : -에 - 문자열 - 투 - 바이트 - 투 - BufferedImage에 자바 로직 로터리이지만, 바이트 스트림을 읽는 것은 바로 같은 오류를 생산

  • 나는 문자 []는 것을 알고 있습니다.
  • 나는 클라이언트 소켓이 영속적이지 않은이 버전의 작업을하고있다. 요청이 처리되고 연결이 끊어집니다. 이미지 크기를 신경 쓸 필요가 없으므로이 버전이 제대로 작동하지만 이유를 제안했습니다. 제안 된 방법이 작동하지 않습니다.
+3

입니다 (크기는 "네트워크 순서"대신 DataInputStream을 사용할 수있는 고정 된 크기의 진 정수 ...로 전송 된 경우) 그건 잘못 될 수 있습니다) 왜 당신은 서버에 바이너리 데이터를 보내지 않습니까? – GETah

+0

당신이 맞습니다. 저는 화학 실험실에서 일하고 있으며, 우리는 역사적으로 논문으로 직접 번역하지 않는 것을 무시합니다. 나는 그것을 고치려고 노력하고 있지만, 나는 경험 많은 코더가 아니다. – PattimusPrime

답변

2
  1. BufferedReader.read()는 버퍼를 채우기 위해 보장하고, 문자열로 이미지를 변환하고 다시 무의미하지만, 잘못뿐만 아니라되지 않습니다.

  2. 문자열은 이진 데이터의 컨테이너가 아니므로 왕복 이동이 보장되지 않습니다.

당신이 readLine() 제거 할 수 있도록 프로토콜을 재 설계하고, 이진 길이를 보내 더 나은 것과 DataInputStream와 전체 스트림을 읽을 수 있습니다.

일반적으로 바이너리 프로토콜을 다룰 때 응답은 항상 DataInputStreamDataOutputStream입니다. 단, 바이트 순서가 표준 네트워크 바이트 순서가 아니거나 프로토콜 디자인 실수가 아닌 경우 바이트를 살펴 봐야합니다. 순서대로 ByteBuffers.

+0

이 진단이 올바르지 않습니다. 그는 동일한 버퍼를 통해 카운트와 이미지를 읽습니다. (문제는 그가 문자 I/O 스택을 통해 이진 데이터를 밀어 내고 있다는 것입니다.) –

+0

@StephenC 합의. 그는 또한'bufferedReader.read (buf, 0, size)'가 버퍼를 채우고 있다고 가정하고있다. – EJP

+0

나는 모든 것을 32 비트 바이너리로 시작하고'DataInputStream'으로 바꾸었다. 모든 것은 지금 작동합니다 (!), 무작위로 ~ 5 %의 오차가납니다. 나는 분명히이 일을 쓰기에 대해 배우고 더 많이 가지고있다. 어떤 자료를 추천 해 주시겠습니까? 바이너리 프로토콜을 처리 할 때 내 표준 접근 방식 (예. 구글) – PattimusPrime

1

서버 코드에서 sys.getsizeof을 잘못 사용했습니다. 그러면 바이트 테 스트링의 바이트 수, 즉 길이가 len(img_string) 인 반면에 바이트 테 이블의 크기가 반환됩니다. 그것을 보는 중 '\r'가 가능하므로 이미지 데이터의 첫 번째 바이트가 0x0A, 즉로 발생하는 경우 문제가 발생할 수 터미네이터로 '\r'를 사용하여, '\n' 또는 '\n'을 따라 할 때까지

또한, 클라이언트 코드에서 .readLine 방법은 문자를 읽고 '\n'.

+0

감사합니다'로 볼 필요가! 나는 len''에 sys.getsizeof''로 전환하는 확실히 문제가 있었다. 나는 또한'readLine' 접근 방식을 제거. – PattimusPrime

0

이진 데이터 (이미지)를 읽으려면 ReadergetBytes()을 사용하려고합니다.

스택은 기본 소켓 스트림에서 바이트를 가져 와서 (플랫폼의 기본 문자 인코딩을 사용하여) 문자로 변환하고이를 문자열로 반환합니다. 그런 다음 기본 인코딩을 다시 사용하여 문자열 컨텐츠를 다시 바이트로 변환합니다. 문자의 초기 바이트 변환은 이진 데이터의 경우 "손실"될 수 있습니다.

수정은 Reader/BufferedReader를 사용하지 않는 것입니다. InputStreamBufferedInputStream을 사용하십시오. 텍스트로 인코딩 된 이미지 크기를 전송하여 쉽게 만들 수는 없지만 줄 바꿈을 얻을 때까지 한 번에 하나씩 바이트를 읽고이를 손으로 "정수"로 변환하면 처리 할 수 ​​있습니다.

그것은 텍스트 (너무 많은 것들에 바이너리를 변환하는 아주 나쁜 생각은 일반적으로

+0

내가 분명히 여기에 초보자있어 가지고 ... 당신은 "네트워크 순서를"정의 할 수 있을까? 나는이 모든에 다음해야 몇 가지 규칙이 있나요? 난 ' 여기에 어떤 조언을 주셔서 감사합니다 거라고 – PattimusPrime

+1

을 http://en.wikipedia.org/wiki/Network_byte_order#Endianness_in_networking를 참조 @PattimusPrime (또한 빅 엔디안 순서로 알려진, 즉 최상위 바이트 먼저)... –

관련 문제