2015-01-21 8 views
0

내 응용 프로그램은 DataInputStream 및 DataOutputStream을 사용하여 서버와 클라이언트간에 통신합니다. 클라이언트는 웹 사이트에서 내 응용 프로그램에 대한 요청이 될 것이므로 웹 사이트에서 올 수있는 입력을 테스트하기 위해 테스트 클라이언트를 만들었습니다.클라이언트 서버 EOF 오류

내가 사용하기로 결정한 방법은 클라이언트가 전송할 데이터의 크기를 먼저 결정한 다음 데이터를 보낼 정수를 보내는 것입니다. 그래서,이 방법을 테스트하고 있었고 첫 번째 문자열에 대해서는 작동했지만 두 번째 시도에는 작동하지 않았고 두 번째 시도에서 EOF 오류를 보냈습니다. 클라이언트가 연결을 닫았 기 때문에 왜 EOF를 받았는지 이해하지만 들어오는 바이트를 읽지 않아서 스트림에서 여전히 더 많은 읽을 수 있어야합니다.

클라이언트 코드 :

Socket socket = new Socket("127.0.0.1", 9000); 
DataOutputStream os = new DataOutputStream(socket.getOutputStream()); 
os.writeInt("Test String".length()); 
os.write("Test String".getBytes()); 
os.flush(); 
os.writeInt("String".length()); 
os.write("String".getBytes()); 
os.flush(); 
os.close(); 
socket.close(); 

서버 코드 :

byte[] data; 

try{ 
    DataInputStream input = new DataInputStream(client.getInputStream()); 
    DataOutputStream output = new DataOutputStream(client.getOutputStream()); 
     client.setSoTimeout(SOCKET_TIMEOUT); 

    logger.log(Level.INFO, "Client connected with IP: " + client.getInetAddress()); 

    data = readNextPacket(input); 
    if(!(new String(data).contains(PROTOCOL_HEADER))) 
     throw new IOException("Invalid request from client."); 
    else 
     logger.log(Level.INFO, "Valid header: " + new String(data)); 

    data = readNextPacket(input); 
    logger.log(Level.INFO, new String(data)); 
}catch(IOException e){ 
    logger.log(Level.SEVERE, e.getMessage(), e); 
}finally{ 
    try { 
     client.close(); 
    } catch (IOException e) { 
     logger.log(Level.SEVERE, e.getMessage(), e); 
    } 
    logger.log(Level.INFO, "FINISHED"); 
} 

readNextPacket 방법 :

private byte[] readNextPacket(DataInputStream stream) throws IOException{ 
    int bytesToRead = stream.readInt(); 
    ByteArrayOutputStream os = new ByteArrayOutputStream(); 

    if(bytesToRead <= MAX_BYTES){ 
     byte[] data = new byte[bytesToRead]; 

     while(stream.read(data) != -1 && os.size() < bytesToRead){ 
      os.write(data); 
     } 
    } 

    return os.toByteArray(); 
} 

스택 추적 :

java.io.EOFException 
at java.io.DataInputStream.readInt(DataInputStream.java:392) 
at com.schmidt73.bidwriter.handlers.SocketHandler.readNextPacket(SocketHandler.java:1) 
at com.schmidt73.bidwriter.handlers.SocketHandler.parse(SocketHandler.java:16) 
at com.schmidt73.bidwriter.handlers.SocketHandler.start(SocketHandler.java:43) 
at com.schmidt73.bidwriter.BidWriter.main(BidWriter.java:21) 
+0

난 당신이 java.io.ObjectOutputStream.writeObject를 (사용하는 것이 좋습니다)를 아이폰에를 보내는 첫번째의 대신이 방법 ... 자습서 : HTTP : 여기

는 새로운 작업 코드 // www가 .tutorialspoint.com/java/io/objectoutputstream_writeobject.htm; 조건 연산자에서 대괄호를 사용하지 않으려는 경우에는 아무 문제가 없지만 좋은 방법입니다. –

+0

네,하지만 Java 객체에서 데이터를 읽지는 않을 것입니다. 그래서 처음 4 바이트를 int로 변환하기 때문에 readInt()와 writeInt()를 사용하는 것을 선호합니다. 그러나 이것은 내 응용 프로그램에서 문제가되지 않는 것으로 보입니다. – schmidt73

+0

'readNextPacket()'에 작성한 코드가 올바르지 않지만'writeUTF()'를 사용하여 문자열을 작성하고 직접 작성한 내용을 복제하는 대신'readUTF()'로 읽는 것이 좋습니다. 틀리게. – EJP

답변

0

기본적으로 전체 버퍼를 처음 읽지 않은 경우 내 readNextPacket() 메서드는 지정된 것보다 많은 데이터를 읽습니다. 그래서 오프셋을 더하고 이미 읽은 값을 뺀 코드를 read() 메서드로 수정하는 코드를 변경했습니다. 그러나, 그 기본적으로 readFully() 메서드를 복사하고 그럴 이유가 없다는 것을 깨달았습니다, 그래서 난 그냥 readNextPacket() 방법으로 구현했습니다. 여기

private byte[] readNextPacket(DataInputStream stream) throws IOException{ 
    int bytesToRead = stream.readInt(); 
    byte[] data = new byte[bytesToRead]; 

    stream.readFully(data); 
    return data; 
} 
+0

MAX_BYTES 테스트가 필요한 이유는 무엇입니까? 실패 할 경우 길이 단어를 제외한 모든 것을 자동으로 읽지 않으며이 메서드를 다음과 같이 호출하면 기이하게 실패합니다. 나중에 일어나기 위해 디버깅의 악몽을 만드는 것보다 어떤 일이 일어나고 즉시 실패하도록하는 것이 가장 좋습니다. – EJP

+0

네 말이 맞아. – schmidt73