2011-01-28 3 views
4

Java에서 작성된 네트워크 응용 프로그램에서 소켓 위의 ObjectOutputStream 및 ObjectInputStream을 사용하여 메시지를 교환하고 있습니다. 내 코드는 다음과 같습니다Java ObjectOutputStream on Socket not flush() ing

보낸 사람 :

ObjectOutputStream out; 
ObjectInputStream in; 
try{ 
    Socket socket=new Socket(address, port); 
    socket.setSoLinger(true, socketLingerTime); 
    out=new ObjectOutputStream(socket.getOutputStream()); 
    out.writeObject(message); 
    out.flush(); 
    out.close(); 
}catch (variousExceptions)... 

수신기 :

Object incoming; 
try{ 
    incoming=myObjectInputStream.readObject(); 
}catch (SocketException socketError) 
{ 
    if (socketError.getMessage().equals("Connection reset")) 
    { 
     //this is the exception I get 
    } 
} 

때때로 메시지가 확인을 통과하지만, 다른 시간 나는 객체 대신 표시된 예외를 얻을. 플러시가 메시지를 다른쪽으로 강제로 전달하지 않습니까? 어떻게 든 함수를 잘못 사용하고 있습니까? 또는 기본 Java/OS 네트워크 코드에서 일종의 버그입니까?

감사합니다.

업데이트 :

나는이에 좀 더 스누핑 짓을했는지, 그리고 시스템의 자원이 무언가에 의해 과세되는 경우에만 일어날 것으로 보인다. VirtualBox 외부에서 복제 할 수 없었지만 VirtualBox에 많은 리소스가 없어서 그럴 수 있습니다. 이 질문은 내가 더 자세히 살펴볼 때마다 계속 업데이트 될 것이다.

+0

문제를 복제 할 수 없습니다. 자세한 내용은? –

+0

더 많은 수신자 코드를 표시 할 수 있습니까? 동일한 소켓을 통해 하나 이상의 메시지를 보내거나 받고 싶습니까 (이 경우 스트림을 닫지 않아야 함). – jtahlborn

+0

리시버에서 연결을 재설정 할 때 보낸 사람 측에서 예외가 발생 했습니까? – nojo

답변

6

Nagle의 알고리즘으로 인해 문제가 발생했습니다. 출력 버퍼는 OS 내에 있으므로 플러시의 영향을받지 않습니다. 해결 방법은 Socket.setTcpNoDelay (true)를 사용하여 Nagle의 알고리즘을 끄고 BufferedOutputStream을 사용하여 사용자 수준에서 메시지를 버퍼링하는 것입니다.

0

연결 당 하나의 개체를 보낼 수 있어야합니다.

리소스가 순서대로 정리되도록하려면 출력 스트림뿐만 아니라 소켓을 닫는 것이 가장 좋습니다.

close()는 flush를 호출하여 중복되어야합니다.

SO 링거를 설정하지 않으면 어떻게됩니까?

실제 예외는 무엇입니까?

+0

여러 개체를 보낼 수 있어야합니다. –

+0

@Highland, 첫 번째 객체를 보낸 후 출력을 닫지 않으면(). ;) –

+0

실제로이 문제에 대한 수정 사항으로 SO Linger를 추가했습니다. 문제가 발생하지 않고 계속 발생합니다. 실제 예외는 SocketException이며 "연결 재설정"메시지입니다. –

0

클라이언트에서 서버로의 경로에있는 라우터 중 하나의 방화벽이 어떤 이유로 RST를 보내는 것처럼 들립니다. 나는 당신의 코드에 문제가 있다고 생각하지 않는다. 문제를 재현하려고 시도했지만 시도 할 수 없었습니다.

0

다른 쪽 끝에서 이미 닫혀있는 연결에 쓰면 연결 재설정이 발생할 수 있습니다. 탐지는 다음 I/O 또는 후속 I/O에서 발생할 수 있습니다. 읽기. 즉, 응용 프로그램 프로토콜의 버그로 인해 발생할 수 있습니다. SO_LINGER는 도움이되지 않습니다.

1

제 경우에는 바보 같은 문제이지만 4 시간을 낭비합니다. 그냥 사용해야합니다 outStream.writeln (""); 또는 outStream.write (혼잡 + "\ n"); 이후 reader.readLine()'\ n' 문자를 찾을 때까지 읽습니다. write()만으로는 작동하지 않습니다.