2013-03-04 2 views
4

아래 코드를 사용하여 데이터를 tcp 서버에 보내고 있습니다. 클라이언트가 요청을 완료했음을 적절히 나타내려면 socket.shutdownOutput()을 사용해야한다고 가정합니다. 내 가정이 맞습니까? 그렇지 않다면 shutdownOutput()의 목적을 알려주십시오. 또한 내가 할 수있는 추가 최적화에 대해 감사드립니다.socket.shutdownOutput() 목적

클라이언트

def address = new InetSocketAddress(tcpIpAddress, tcpPort as Integer) 
clientSocket = new Socket() 
clientSocket.connect(address, FIVE_SECONDS) 
clientSocket.setSoTimeout(FIVE_SECONDS) 

// default to 4K when writing to the server 
BufferedOutputStream outputStream = new BufferedOutputStream(clientSocket.getOutputStream(), 4096) 

//encode the data 
final byte[] bytes = reqFFF.getBytes("8859_1") 
outputStream.write(bytes,0,bytes.length) 
outputStream.flush() 
clientSocket.shutdownOutput() 

서버

ServerSocket welcomeSocket = new ServerSocket(6789) 

while(true) 
{ 
    println "ready to accept connections" 
    Socket connectionSocket = welcomeSocket.accept() 
    println "accepted client req" 
    BufferedInputStream inFromClient = new BufferedInputStream(connectionSocket.getInputStream()) 
    BufferedOutputStream outToClient = new BufferedOutputStream(connectionSocket.getOutputStream()) 
    ByteArrayOutputStream bos=new ByteArrayOutputStream() 

    println "reading data byte by byte" 
    byte b=inFromClient.read()  
    while(b!=-1) 
    {   
     bos.write(b) 
     b=inFromClient.read() 
    } 
    String s=bos.toString() 

    println("Received request: [" + s +"]") 

    def resp = "InvalidInput" 
    if(s=="hit") { resp = "some data" } 

    println "Sending resp: ["+resp+"]" 

    outToClient.write(resp.getBytes()); 
    outToClient.flush() 
} 

답변

4

Socket.shutdownOutput() 클라이언트가 TCP 연결을 통해 데이터를 전송 완료된 것을 의미한다. 나머지 데이터를 보내고 종료 시퀀스를 수행하여 OUTGOING 연결을 완전히 닫습니다. 추가 데이터를 보낼 수 없으므로 프로그램에 요청이 완전히 완료되었음을 나타냅니다. 그래서 더 이상 데이터를 보낼 필요가 없다고 확신한다면 추천합니다.

하지만 요청이 완료되었음을 나타낼 필요는 없습니다 (여러 요청을하는 경우 항상 출력을 열거 나 닫을 필요가 없습니다). 다른 방법이 있습니다.

+0

+1 당신은 그러나 그 요청이 완료되었음을 나타 내기 위해 필요한 (당신은 출력을 닫으/열 필요하지는 없습니다 "에 정교한 모든 여러 요청이있는 경우 시간), 다른 방법이 있습니다. " –

+0

서버에 보낼 요청이 여러 개인 경우 "마법 패키지"(특수한 ** 고유 바이트 배열 **)를 정의 할 수 있으며이를 보내면 하나의 요청이 끝난 서버를 나타냅니다. – Leander

+0

간단한 예제 (더 정교하고 중요한 프로그램에는 적합하지 않음)는 문자열 "End"의 바이트 배열이 될 것이며 문자열을 보내지 않는다고 가정합니다. – Leander

8

아래 코드를 사용하여 데이터를 tcp 서버에 보내고 있습니다. 나는 을 적절히 나타내려면 socket.shutdownOutput()을 사용해야한다고 가정하고 있는데, 클라이언트가 요청을 보내는 것을 은 완료했다. 내 가정이 맞습니까?

YES 귀하의 가정이 올바른 것입니다. 이 출력 종료는 반 폐쇄으로 알려져 있습니다. 반쪽 닫기를 사용하면 TCP는 연결의 한쪽 끝이 출력을 종료하고 다른 쪽 끝에서 데이터를받는 기능을 제공합니다. 나를 socket.shutdownOutput() 방법의 효과 과정을 살펴 보겠습니다 : 목적을 읽기 위해

  1. 로컬, 로컬 소켓의 입력 스트림이 정상적으로 작동하지만, 쓰기의 목적을 위해 소켓과 출력 스트림 소켓 것처럼 행동 소켓에 대한 후속 쓰기가 발생합니다. IOException
  2. 보류중인 데이터가 보내고 승인 된 후 TCP의 정상적인 연결 종료 시퀀스 (ACK가 에 의해 ACK 되었음)가 대기열에 대기합니다. .
  3. 원격 소켓은 쓰기 목적으로 정상적으로 작동하지만 읽기 용도로 소켓은 마치 끝으로 소켓이 닫힌 것처럼 동작합니다. 소켓에서 추가 읽기는 EOF 조건, 즉 읽기 수를 반환합니다. of - 1 또는 EOFException을 호출 할 수 있습니다.
  4. 로컬 소켓이 마지막으로 닫히면 연결 종료 시퀀스 이 이미 전송되었으므로 반복되지 않습니다. 다른 쪽 끝이 이미 인 경우에도 소켓의 모든 프로토콜 교환은 이제 이 완료되었습니다.

따라서 EOF를 받으면 다른 쪽 끝이 출력 종료를 확인했습니다. 그리고이 시나리오는 다른쪽에 socket.shutDownOutput()에 의해 완벽하게 달성됩니다.

출처 : 자바에서 기본 네트워킹, Esmond 피트