들어가기
C언어를 이용해 네트워크 프로그래밍 수업을 들으며 처음으로 소켓을 이용한 통신을 주고 받아 봤다.
나도 모르는 사이 많은 응용 프로그램을 이용하면서 소켓을 사용했겠지만, 그 내부를 공부하고 구현해 본적은 당연히 없었다...
C언어를 통해 윈도우 소켓 프로그래밍을 해보았지만, 자바/스프링 개발자가 되고싶은 나에겐 자바로 소켓 통신을 구현해보고 싶은 생각이 들었고
지금 해보려한다.
소켓 생성
public class WebServer {
private static final Logger logger = LoggerFactory.getLogger(WebServer.class);
private static final int DEFAULT_PORT = 8080;
private static final int BACK_LOG = 5;
private static ServerSocket serverSocket=null;
public static void main(String[] args) throws IOException {
try{
serverSocket = new ServerSocket(DEFAULT_PORT,BACK_LOG);
logger.info("WebServer Started {} port",DEFAULT_PORT);
}catch (IOException e){
logger.error(e.getMessage());
}
}
}
C언어로 작성할 때와는 조금 다르다.
C언어에서 흐름은 socket() [소켓 생성] -> bind() [주소,포트] -> listen() [백로그 설정]-> accept() [연결 대기] -> 통신 이다.
자바에서는 ServerSocket listener = new ServerSocket(DEFAULT_PORT,BACK_LOG);
으로 소켓을 생성하고 주소,포트를 설정하고 백로그까지 설정한다.
사실 내부를 들여다보면 socket() , bind(), listen() 과정을 수행하고 있다.
public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException {
setImpl(); // 여기서 소켓 생성
if (port < 0 || port > 0xFFFF)
throw new IllegalArgumentException(
"Port value out of range: " + port);
if (backlog < 1)
backlog = 50; // 백로그가 1미만일 경우
try {
bind(new InetSocketAddress(bindAddr, port), backlog); // 주소,포트 백로그 설정
} catch(SecurityException e) {
close();
throw e;
} catch(IOException e) {
close();
throw e;
}
}
// bind() 내부
try {
@SuppressWarnings("removal")
SecurityManager security = System.getSecurityManager();
if (security != null)
security.checkListen(epoint.getPort());
getImpl().bind(epoint.getAddress(), epoint.getPort());
// listen()에 백로그 설정
getImpl().listen(backlog);
bound = true;
}
객체를 생성하는 시점에 내부에서 설정이 이루어지기 때문에 따로 bind()나 listen()을 호출하지 않아도 되긴하지만
공부할 겸 bind()를 직접 호출해보자.
serverSocket.bind(
new InetSocketAddress(serverSocket.getInetAddress(),DEFAULT_PORT)
,BACK_LOG
);
소켓에서 InetAddress()를 통해 IP주소와 위에서 선언한 기본 포트, 백로그 값을 설정하면 된다.
BACK_LOG는 TCP 연결 대기 큐 사이즈다. 총 5개가 대기열에 들어갈 수 있고 그 외에는 거부된다.(이것도 실험해보자!)
이렇게 설정하고 실행한 결과는 아래와 같다.
지금은 accept() 처리를 하지 않아서 수신을 대기하지 않는다.
Accept()
public class WebServer {
private static final Logger logger = LoggerFactory.getLogger(WebServer.class);
private static final int DEFAULT_PORT = 8080;
private static final int BACK_LOG = 5;
private static final ServerSocket listener=null;
public static void main(String[] args) throws IOException {
try{
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(
new InetSocketAddress(serverSocket.getInetAddress(),DEFAULT_PORT)
,BACK_LOG
);
logger.info("WebServer Started {} port",DEFAULT_PORT);
Socket client;
// 계속해서 반복
while((client = serverSocket.accept()) != null){
// 연결되면 로그 출력
logger.info("Success");
}
}catch (IOException e){
logger.error(e.getMessage());
}
}
}
http://localhost:8080에 접속해보자.
4번 요청했고 Success가 성공적으로 4번 출력됐다.
하지만 로그만 서버내부에서 찍도록 설정했기 때문에 클라이언트는 응답을 계속 기다리며 무한 로딩된다.
마치며
다음 포스팅에선 클라이언트 HTTP 메세지를 받아 출력해보자.
'Java' 카테고리의 다른 글
[WAS를 만들어보자 (3)] HttpMessageBody 추출하기 (1) | 2024.03.23 |
---|---|
[WAS를 만들어보자 (2)] HTTP 메세지 출력하기 (0) | 2024.03.23 |
Faker를 이용한 테스트데이터 만들기 + 데이터 30만건 밀어넣기 (0) | 2023.07.16 |
Exception Performance Cost (0) | 2023.07.05 |
사이드프로젝트::BlackJack 되돌아보기 (0) | 2023.04.27 |