티스토리 뷰
반응형
socket connection timeout 랑 read timeout 설정 가능한 클라이언트용 Socket util만들어보기
connection time => 접속 대기 시간
socket.connect(new InetSocketAddress(host, port), 3000);
3초간 접속안되면 SocketTimeoutException 발생
read timeout ==> 응답 대기 시간
socket.setSoTimeout(3000);
3초동안 응답(패킷수신)이 없을 경우 SocketTimeoutException 발생
ClientSocketUtil
기본 connectionTimeout 3초, readTimeout 3초
public class ClientSocketUtils {
private static final int DEFAULT_CONNECT_TIMEOUT = 3000;
private static final int DEFAULT_READ_TIMEOUT = 3000;
public static byte[] request(String url, int port, byte[] sendBytes, int readByteLength) {
return request(url, port, sendBytes, readByteLength,DEFAULT_CONNECT_TIMEOUT, DEFAULT_READ_TIMEOUT);
}
public static byte[] request(String url, int port, byte[] sendBytes, SocketReadFunction readHandler) {
return request(url, port, sendBytes, readHandler, DEFAULT_CONNECT_TIMEOUT, DEFAULT_READ_TIMEOUT);
}
public static byte[] request(String url, int port, byte[] sendBytes, int readByteLength, int connectTimeout, int readTimeout) {
return request(url, port, sendBytes, (inputStream) -> {
byte[] readBytes = new byte[readByteLength];
inputStream.read(readBytes);
return readBytes;
}, connectTimeout, readTimeout);
}
public static byte[] request(String host, int port, byte[] sendBytes, SocketReadFunction readHandler, int connectTimeout, int readTimeout) {
Socket socket = new Socket();
BufferedOutputStream bufferedOutputStream = null;
BufferedInputStream bufferedInputStream = null;
try {
socket.connect(new InetSocketAddress(host, port), connectTimeout);
socket.setSoTimeout(readTimeout);
bufferedInputStream = new BufferedInputStream(socket.getInputStream());
return readHandler.read(bufferedInputStream);
} catch (SocketTimeoutException ste) {
throw new RuntimeException(ste);
} catch (IOException ioe) {
throw new RuntimeException(ioe);
} finally {
IOUtils.closeQuietly(bufferedOutputStream);
IOUtils.closeQuietly(bufferedInputStream);
IOUtils.closeQuietly(socket);
}
}
}
public interface SocketReadFunction {
byte[] read(BufferedInputStream input) throws IOException;
}
ClientSocketUtil을 사용하는 샘플 코드
소켓통신으로 국민은행 조회(search), 출금(withdraw), 입금(deposit) 요청 전문을 호출하는 샘플 코드
public class KBSocket {
private static String host = "127.0.0.1";
private static int port = 20009;
public byte[] search(ByteTranslatable request) {
byte[] response = ClientSocketUtils.request(host, port, request.toBytes(), 1000);
//request bytes를 보내고 1000바이트 응답값을 받는다.
return response;
}
public byte[] withdraw(ByteTranslatable request) {
byte[] head = new byte[4];
byte[] response = ClientSocketUtils.request(host, port, request.toBytes(), (input) -> {
input.read(head);
byte[] data = new byte[Integer.parseInt(new String(head))];
input.read(data);
return ArrayUtils.addAll(head, data);
});
//request bytes를 보내고 헤더4바이트 읽고, 헤더에 명시된 본문길이만큼 다시 읽어서 응답받음
return response;
}
public byte[] deposit(ByteTranslatable request) {
byte[] body = ClientSocketUtils.request(host, port, request.toBytes(), this::receiveDepositResponse, 1000, 30000);
//request bytes를 보내고 헤더4바이트 읽고, 헤더에 명시된 본문길이만큼 다시 읽어서 응답받음
//connection timeout은 1초, 입금처리는 오래걸릴수 있으므로 read timeout은 30초
return body;
}
public byte[] receiveDepositResponse(BufferedInputStream in) throws IOException {
byte[] head = new byte[4];
in.read(head);
byte[] data = new byte[Integer.parseInt(new String(head))];
in.read(data);
return data;
}
interface ByteTranslatable {
byte[] toBytes();
}
}
ClientSocketUtil 개선해보기
public byte[] receiveDepositResponse(BufferedInputStream in) throws IOException {
byte[] head = new byte[4];
in.read(head);
byte[] data = new byte[Integer.parseInt(new String(head))];
in.read(data);
return data;
}
1.일반적으로 소켓통신 시 응답데이터를 받는 로직이 다양해서(고정길이읽기, 종료문자받기, 고정읽기+가변읽기 등) 수신 구현 확장가능하도록 SocketReadFunction인터페이스 둠 -> 응답 데이터 받는 로직이 같을 때마다 코드 중복이 발생함 -> 일반적인 읽기 구현 제공
*SocketReadFunction인터페이스도 Function<T,R>대체 가능
2. ClientSocketUtil,request메소드는 내부적으로 connect, write, read 여러 동작을 함 -> SocketTimeoutException이 발생하면connectTimeout인지 readTimeout인지 exception message로만 판단이 가능함. 메소드에 맞는 예외추상화하기
개선은 다음 편에
반응형
'Java' 카테고리의 다른 글
ClientSocketUtil 개선버전 (0) | 2023.04.12 |
---|---|
자바 동기화 처리 - volatile 와 synchronized (1) | 2020.11.25 |
synchronized 와 Double-checked locking (0) | 2020.11.20 |
Optional에 대해.... (0) | 2020.10.22 |
ThreadPoolExecutor (0) | 2017.01.09 |
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 바이트 기반 서버
- 자바소켓
- neso
- 상속과 구성
- 자바 온라인 사천성
- RedisAutoConfiguration
- socket connection timeout
- 자바 사천성
- 자바 동기화
- 소켓통신 프레임워크
- netty
- 추상 팩토리 패턴
- 디자인 패턴
- socket readtimeout
- 자바 tcp
- client socket util
- 자바 TCP 서버
- 자바 전문서버
- 클라이언트 소켓 유틸
- 구성
- java socket util
- 자바 클라이어트 소켓
- 클라이언트 소켓
- 사천성 게임
- 자바 소켓통신
- 소켓통신
- 사천성 알고리즘
- 자바 전문통신
- 소켓 유틸
- java socket
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함