2012-12-08 3 views
1

다른 소켓이 닫혀있는 동안 소켓에서 읽으려고 할 때 다른 결과가 나타납니다. >를 읽은 데이터 - -Java 닫는 소켓이 다른 결과를냅니다.

I는 두 개의 소켓 A 및 B.

1) B는 일부 데이터를 전송 가지고 닫을> -> B는 일부 데이터를 판독하려고하면 그것은 -1 (또는 EOF)를 얻고 있습니다.

2) B는 데이터를 읽기 전에도 A -> A 데이터를 닫습니다. -> 이제 B가 A에서 읽으려고 시도하면 예외가 throw됩니다 (java.net.SocketException "소프트웨어로 인해 연결이 중단되었습니다.").)

제 질문을 이해할 수 없다면 제발 실례합니다.

import java.io.*; 
import java.net.*; 


class SocketCloser extends Thread 
{ 
    private Socket c; 
    public SocketCloser(Socket c) { 
     this.c = c; 
    } 

    public void run() { 

     try{ 
      this.c.close(); 
     } catch (Exception e) {} 
    } 
} 


public class Server 
{ 
    public static void main(String argv[]) throws Exception { 
     ServerSocket listen = new ServerSocket(6789); 

     Socket socket = listen.accept(); 
     SocketCloser sc = new SocketCloser(socket); 
     InputStream is = socket.getInputStream(); 
     // uncomment below line to get "Software caused connection abort" on client 
     //sc.start(); 
     try { 
      Thread.sleep(1000); 
      int i = is.read(); 
      System.out.println("read returned: " + i); 
      socket.close(); 
     } catch (Exception e) { 
      System.out.println(e.toString() + " thrown"); 
     } 
    } 
} 

Client.java

import java.io.*; 
import java.net.*; 

public class Client 
{ 
    public static void main(String argv[]) 
    { 
     Socket cSocket; 
     try { 
      cSocket = new Socket("localhost", 6789); 
      InputStream is = cSocket.getInputStream(); 
      OutputStream os = cSocket.getOutputStream(); 
      Thread.sleep(1000); 
      os.write(200); 
      Thread.sleep(1000); 
      int i = is.read(); 
      System.out.println("read returned: " + i); 
      cSocket.close(); 
     } catch (Exception e) { 
      System.out.println(e.toString() + " thrown"); 
     } 
    } 
} 

사람이 하나의 케이스와 다른 -1에서 예외가 왜 저를 알아내는 데 도움 주실 래요 코드

Server.java를 참조하십시오. 리눅스에 흥미롭게도 두 경우 모두 -1이되었습니다.

+0

답변은 [TCP 연결 수명]의 다른 단계 (http : //www.sdsusa.co.kr/connections /) - 연결을 닫을 때 많은 트랜잭션이 발생합니다. –

답변

0

1) B가 연결을 설정 했으므로 A는 CLOSE_WAIT으로 이동합니다. B가 연결을 닫을 때까지 그 상태가됩니다. 읽을 것이 없으므로 B의 InputStream에 대한 read() 호출은 -1을 반환합니다.

2) 수락 호출에서 A가 차단됩니다. 다른 스레드가 소켓을 닫으려고하지만 accept가 소켓을 차단하고 있기 때문에 그렇게 할 수 없습니다. B가 연결되면 차단 해제가 적용되고 소켓은 완전히 닫힙니다. B가 읽기를 시도 할 때 소켓이 더 이상 존재하지 않으므로 예외가 발생합니다.

저는 조금 단순화하고 있지만 그게 요점입니다.

+0

2의 경우, 리눅스에서 프로그램을 실행할 때 예외가 발생해야하지만 이상적으로 리눅스에서 -1이 반환됩니다. – RAghu

0

1) B가 데이터를 보냄 A -> A가 데이터를 읽음 -> A가 닫힘 -> B가 A에서 일부 데이터를 읽으려고 시도 할 때 -1 (또는 EOF)이 발생합니다.

동의합니다. 너는 무엇을 기대 했는가? 이것이 예상되는 동작입니다. 심지어 데이터를 읽기 전에>를 닫습니다 - -이

2) B는 A를 일부 데이터를 전송> 이제 B가 A로부터 읽기를 시도, 예외가 발생합니다 (java.net.SocketException의 "소프트웨어 인한 접속 중단 . ")

동의합니다. 이 잘못된 상황에서 예상되는 동작 중 하나입니다. 너는 무엇을 기대 했는가?

제 질문에 대해 이해할 수없는 경우 실례합니다.

여기 이해할 질문이 없습니다. 너는 질문하지 않았다. 데이터를 보내지 않고 소켓을 닫으면 상대방은 데이터를받지 않고 EOS를 얻습니다. 피어가 보내고 피어가 예외를 가져 오는 동안 소켓을 닫습니다. 시스템이 설계대로 작동합니다.

+0

이것은 윈도우 (JDK 1.6.0_23)에서 얻은 동작입니다. 하지만 리눅스에서 (OpenJDK 1.7.0_09와 SunJDK 1.6.0_20) 나는 두 경우 모두 -1을 받았다. 다른 플랫폼에서 다른 결과를 얻었습니다. 나에게 설명해 주시겠습니까? 어떤 플랫폼에서 올바르게 작동합니까? 그 이유는 무엇입니까? – RAghu

+1

@RAghu Your (2)가 잘못된 상황입니다. 잘못된 상황에 대해 정의 된 올바른 동작이 없습니다. TCP 버퍼링의 차이점으로 인해 다른 동작을 설명 할 수는 있지만 피어가 읽지 않는 데이터를 보내지 않아도됩니다. – EJP

관련 문제