1

나는 의 ObjectInputStream/ObjectOutputStream에 주위에 내 머리를 얻으려고, 그래서 클라이언트가 생성 된 스트림을 통해는 HashMap 객체를 전송하는 매우 간단한 서버 - 클라이언트 응용 프로그램을 작성하고 서버가이를 수신하여 인쇄합니다.의 SocketException : 연결이 ObjectInputStream를 함께 서버에 다시

이 내 서버 코드 :

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

public class Server { 

    public static void main(String[] args) throws IOException, ClassNotFoundException { 
     ServerSocket server = new ServerSocket(4444); 
     while (true) { 
      Socket socket = server.accept(); 
      ObjectInputStream objIn = new ObjectInputStream(socket.getInputStream()); 

      if (objIn.readObject() != null) { 
       System.out.println(objIn.readObject()); 
      } 
     }  
    } 
} 

이 내 클라이언트 코드 :

import java.io.*; 
import java.net.InetAddress; 
import java.net.Socket; 
import java.util.HashMap; 

public class Client { 

    public static void main(String[] args) throws IOException { 
     Socket sock; 
     int port = 4444; 
     HashMap<Integer, String> mapSend= new HashMap<>(); 
     mapSend.put(1,"row1"); 
     mapSend.put(2,"row2"); 

     sock = new Socket(InetAddress.getLocalHost(), port); 
     ObjectOutputStream objOut = new ObjectOutputStream(sock.getOutputStream()); 

     objOut.writeObject(mapSend); 
     objOut.flush(); 
    } 
} 

나는 서버 파일을 실행하고 확인을 실행합니다. 그런 다음
나는 클라이언트 파일을 실행하고 나는 서버에 다음과 같은 오류가 발생합니다 :

Exception in thread "main" java.net.SocketException: Connection reset 
    at java.net.SocketInputStream.read(SocketInputStream.java:189) 
    at java.net.SocketInputStream.read(SocketInputStream.java:121) 
    at java.io.ObjectInputStream$PeekInputStream.read(ObjectInputStream.java:2308) 
    at java.io.ObjectInputStream$BlockDataInputStream.read(ObjectInputStream.java:2716) 
    at java.io.ObjectInputStream$BlockDataInputStream.readFully(ObjectInputStream.java:2740) 
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1978) 
    at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:499) 
    at java.util.HashMap.readObject(HashMap.java:1115) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017) 
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1891) 
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796) 
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348) 
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370) 
    at iotest.Server.main(Server.java:17) 
Java Result: 1 

P.S. HashMap을 직렬화하기 위해 무언가를해야하는지는 모르겠지만 자바가 내부적으로 처리하는 것을 보았다고 생각합니다. 나는 힘들 수도 있습니다.

Object objRead=objIn.readObject(); 
      if (objRead != null) { 
       System.out.println(objRead); 
      } 

을 나는 클라이언트 실행 한 후 지금은, 서버에서 다시이 오류를 얻을 : 나는 아론으로 내 서버에서이 부분을 구현 아론 응답 후

수정 제안

Exception in thread "main" java.net.SocketException: Connection reset 
    at java.net.SocketInputStream.read(SocketInputStream.java:189) 
    at java.net.SocketInputStream.read(SocketInputStream.java:121) 
    at java.io.ObjectInputStream$PeekInputStream.read(ObjectInputStream.java:2308) 
    at java.io.ObjectInputStream$BlockDataInputStream.read(ObjectInputStream.java:2716) 
    at java.io.ObjectInputStream$BlockDataInputStream.readFully(ObjectInputStream.java:2740) 
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1978) 
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1913) 
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796) 
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348) 
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370) 
    at java.util.HashMap.readObject(HashMap.java:1154) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017) 
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1891) 
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796) 
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348) 
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370) 
    at iotest.Server.main(Server.java:17) 
Java Result: 1 

답변

1

개체를 두 번 읽었지만 두 번째로만 인쇄합니다. 그래서 두 번째 시간을 읽을 때까지 클라이언트가 종료 될 것이므로 소켓이 원격 끝에 닫혀 있으므로 예외가 발생합니다.

! = null 확인을 사용하여 개체를 읽는 중입니다. 인쇄하지 마십시오. 그런 다음 다시 읽으려고하면 폭탄이 터집니다.

스트림에서 읽으면 읽었습니다. 스트림이 아니고 버퍼입니다. 읽은 것을 버퍼링하고 원하는만큼 버퍼를 검사 할 수 있습니다.

간단한 예를 ...

Object o = outputStream.readObject(); 
if(o != null) { 
system.out.println(o); 
} 
+0

예. 핵심은 스트림이 버퍼링되지 않는다는 것을 기억하는 것입니다. 일단 당신이 그것을 읽었 으면, 그것은 사라졌습니다. – Aaron

+0

실수로 내 의견을 삭제했습니다. 설명해 주셔서 대단히 감사합니다. – akafortes

+0

@akafortes 맥주 통을 켤 때와 마찬가지로 맥주를 켜서 남은 맥주가 있는지 확인할 수 있습니다. 그러나 쏟은 맥주를 유리에 담지 않으면 맥주를 사용할 수 없습니다. 그 다음에 이미 엎질 렸던 맥주를 마시려고 노력합니다. – Aaron

1

클라이언트 소켓이 자동으로 모든 코드가 실행되어 그 후 종료하기 때문에 이런 일이. 클라이언트 소켓이 종료되지 않습니다 때문에 예를 들어

, 당신은 당신의 클라이언트 코드의 끝 부분에

while (true) { 
    System.out.println("no operation"); 
    try { 
     Thread.sleep(10000); 
    } catch(InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 

를 추가하는 경우, 당신은 어떤 연결 재설정을하지 않습니다.

따라서 클라이언트 측 소켓이 닫히고 서버 측 소켓이이 예외를 처리해야합니다. 이 예외가 발생하면 루프에서 빠져 나와야합니다.