java.net.SocketException: recvfrom failed: ECONNRESET (Connection reset by peer) at libcore.io.IoBridge.maybeThrowAfterRecvfrom(IoBridge.java:592) at libcore.io.IoBridge.recvfrom(IoBridge.java:556) at java.net.PlainSocketImpl.read(PlainSocketImpl.java:485) at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:37) at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:237) at com.android.okio.Okio$2.read(Okio.java:116) at com.android.okio.RealBufferedSource.read(RealBufferedSource.java:51) at com.android.okhttp.internal.http.HttpConnection$FixedLengthSource.read(HttpConnection.java:469) at com.android.okio.RealBufferedSource$1.read(RealBufferedSource.java:174) at java.io.InputStream.read(InputStream.java:162) ... Caused by: android.system.ErrnoException: recvfrom failed: ECONNRESET (Connection reset by peer) at libcore.io.Posix.recvfromBytes(Native Method) at libcore.io.Posix.recvfrom(Posix.java:161) at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:250) at libcore.io.IoBridge.recvfrom(IoBridge.java:553) ... 14 more
위 에러는 서버에서 RST응답이 도착하여, socket이 닫혔다는 뜻이다. 위 상황은 보통 서버가 어떠한 이유(전원 차단, 시스템 오류 등)으로 이전의 연결 데이터를 잃어버렸고, 클라이언트는 여전히 socket을 연결하고 있을 때, 클라이언트가 서버에 연결을 시도했을 때 발생한다. TCP/IP 스펙 상 RST는 서버(peer)에서 현재 연결을 기억하지 못하고 있으니 클라이언트에서 스스로 socket을 닫거나 재시도할 수 있도록 알려줄 때 보낸다. 물론 FIN을 통해 연결을 정상적으로 종료하면 좋지만, 그나마 우아한 방법이라고 할 수 있다. 만약, RST를 받지 못한다면 클라이언트는 연결된 socket을 통해 데이터를 계속 보내거나 읽으려고 시도할 것이기 때문이다.
위 에러가 난다면, 일단 클라이언트에서 현재 socket 인스턴스를 통해 서버와 연결할 방법은 없으니 에러를 표시하거나, socket을 통해 새로 연결하여 재시도 하는 것이 옳다.
기타
일부 하드웨어의 경우, 서버에 연결할 방법이 끊긴 경우 서버에서 마치 RST가 온것처럼 어플리케이션에 RST를 전달하는 경우가 있다고 한다. 안드로이드에서도 동일한지는 확인이 필요하다.
참고