Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
Tags
- WildFly
- Reading HttpServletRequest Multiple Times
- Unchecked Exception
- NoUniqueBeanDefinitionException
- Sub Bytes
- Java Rest
- mTLS
- Tomcat DBCP
- Graphql Client
- Checked Exception
- mapstruct
- Jndi DataSource
- 개방 폐쇄 원칙
- AfterMapping
- Java Singleton
- 상호 인증
- 데이터 압축
- try - with - resources
- Open Close Principal
- graphql
- Srping MVC
- tomcat jndi
- java
- requestheaderdto
- 이중정렬
- HandlerMethodArgumentResolver
- Socket is closed
- 바이트 절삭
- Java Graphql
- Request Body 여러 번 사용
Archives
- Today
- Total
Developer Sang Guy
Socket is closed 본문
SocketUtil 클래스를 생성하여 Socket 통신 테스트를 진행하였더니 "Socket is closed" 라는 에러를 만나게 되었다.
해당 에러는 소켓을 사용하려 할 때 이미 소켓이 닫혀 버린 경우 발생하는 에러이다.
Socket.class
public OutputStream getOutputStream() throws IOException {
if (isClosed())
throw new SocketException("Socket is closed");
if (!isConnected())
throw new SocketException("Socket is not connected");
if (isOutputShutdown())
throw new SocketException("Socket output is shutdown");
OutputStream out = this.out;
if (out == null) {
// wrap the output stream so that the close method closes this socket
out = new SocketOutputStream(this, impl.getOutputStream());
if (!OUT.compareAndSet(this, null, out)) {
out = this.out;
}
}
return out;
}
public InputStream getInputStream() throws IOException {
if (isClosed())
throw new SocketException("Socket is closed");
if (!isConnected())
throw new SocketException("Socket is not connected");
if (isInputShutdown())
throw new SocketException("Socket input is shutdown");
InputStream in = this.in;
if (in == null) {
// wrap the input stream so that the close method closes this socket
in = new SocketInputStream(this, impl.getInputStream());
if (!IN.compareAndSet(this, null, in)) {
in = this.in;
}
}
return in;
}
어떻게 소스 코드를 작성하여 해당 에러가 발생했는지와 어떻게 해결하였는지 기록하겠다.
Socket is closed 발생 Case
SocketUtil.class
public static Socket getConnection(String ip, int port) throws Exception {
SocketAddress socketAddress = new InetSocketAddress(ip, port);
Socket socket = new Socket();
socket.connect(socketAddress, 5 * 1000);
socket.setSoTimeout(5 * 1000);
return socket;
}
public static int send(Socket socket, String msg, String charset) throws Exception {
try (DataOutputStream dos = new DataOutputStream(socket.getOutputStream())) {
dos.write(msg.getBytes(charset));
return dos.size();
}
}
public static String recv(Socket socket, String charset) throws Exception {
try (BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), charset))) {
StringBuffer sb = new StringBuffer();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
sb.append("\n");
}
return sb.toString();
}
}
Main.class
public static void main(String[] args) {
String ip = "연결할 IP";
int port = 25000; // 연결 할 Port
String msg = "전달할 데이터";
String charset = "UTF-8";
try (Socket socket = SocketUtil.getConnection(ip, port)) {
int sendLength = SocketUtil.send(socket, msg, charset);
if (sendLength != msg.getBytes(charset).length) {
throw new Exception("데이터가 올바르게 전달되지 않음");
}
String result = SocketUtil.recv(socket, charset);
System.out.println("응답 데이터 : " + result);
} catch (Exception e) {
System.out.println("Exception 발생 : " + e);
}
}
위 main 메소드에 올바른 ip와 port를 입력하여 실행하면 "socket is closed"가 발생한다.
일단 원인은 SocketUtil.class의 send() Method에서 사용 된 try - with - resource AutoCloseable 기능 때문이다.
OutputStream을 상속받아 구현한 SocketOutputStream.class의 Override 된 close() Method가 try - with - resource에 의해 호출되어 Socket가 Close 되었다.
Socket.class
private static class SocketOutputStream extends OutputStream {
private final Socket parent;
private final OutputStream out;
SocketOutputStream(Socket parent, OutputStream out) {
this.parent = parent;
this.out = out;
}
@Override
public void write(int b) throws IOException {
byte[] a = new byte[] { (byte) b };
write(a, 0, 1);
}
@Override
public void write(byte b[], int off, int len) throws IOException {
out.write(b, off, len);
}
@Override
public void close() throws IOException {
parent.close();
}
}
데이터를 전송한 이 후에 recv() Method가 실행 될 때까지는 Socket이 열려있어야 하기때문에 아래와 같이 소스를 수정하여 해당 이슈를 해소하였다.
보완 Case
SocketUtil.class
public static DataOutputStream send(Socket socket, String msg, String charset) throws Exception {
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.write(msg.getBytes(charset));
return dos;
}
Main.class
public static void main(String[] args) {
String ip = "연결할 IP";
int port = 25000; // 연결 할 Port
String msg = "전달할 데이터";
String charset = "UTF-8";
try {
Socket socket = SocketUtil.getConnection(ip, port);
try (DataOutputStream dos = SocketUtil.send(socket, msg, charset)) {
int sendLength = dos.size();
if (sendLength != msg.getBytes(charset).length) {
throw new Exception("데이터가 올바르게 전달되지 않음");
}
String result = SocketUtil.recv(socket, charset);
System.out.println("응답 데이터 : " + result);
}
} catch (Exception e) {
System.out.println("Exception 발생 : " + e);
}
}
try (DataOutputStream dos = SocketUtil.send(socket, msg, charset)) 에 의하여 Socket가 Close되는 것을 확인하여 Socket socket = SocketUtil.send(socket, msg, charset) 해당 코드는 try - with - resource을 사용할 필요가 없어 제거하였다.
'Java' 카테고리의 다른 글
[JWT] Auth0을 활용한 JWT 생성 및 확인 (0) | 2023.04.10 |
---|---|
[Java] Class에서 파일 읽어오기 (tomcat, wildfly) (0) | 2023.02.02 |
Checked Exception, Unchecked Exception (1) | 2022.11.26 |
데이터 압축 (0) | 2022.05.26 |
[Java]NonStaticInnerClass vs StaticInnerClass (0) | 2022.05.18 |
Comments