막연하게만 사용하던 I/O를 조금 더 이해해보고자 작성한 글입니다.
기본적으로 I/O는 O/S 레벨에서 이루어지고 byte를 다룬다는 것을 생각야해합니다.
네트워크를 왜 I/O로 분류하는가를 이해해보자.
쓰레드를 사용하지 않고, socket에서 제공하는 Input/Output Stream을 사용해서 간단하게 메세지를 console에서 확인해보자.
우선 원하는 포트를 지정해서 응답을 기다리는 서버를 만든다.
서버에 도착한 stream을 console에 출력해보자.
// server
public static void main(String[] args) {
ServerSocket serverSocket = new ServerSocket("port");
boolean isRunning = true;
while (isRunning) {
Socket s = serverSocket.accept();
InputStream in = s.getInputStream();
byte[] b = new byte[256];
in.read(b);
System.out.write(b);
System.out.flush();
in.close();
}
}
다음은 준비한 포트 번호로 OutputStream을 흘려보내줄 클라이언트를 만들자.
"Hello from client"라는 텍스트를 OutputStream에 써보자.
// client
public static void main(String[] args) {
Socket s = new Socket("ip", "port");
OutputStream out = s.getOutputStream();
String msg = "Hello from client";
byte[] byteMsg = msg.getBytes();
out.write(byteMsg);
out.flush();
out.close();
s.close();
}
처음 클라이언트에서 메세지를 보냈던 것과 동일한 방법으로 서버에서도 OutputStream을 사용해서 메세지를 보낼 수 있다.
// server
public static void main(String[] args) {
ServerSocket serverSocket = new ServerSocket("port");
boolean isRunning = true;
while (isRunning) {
Socket s = serverSocket.accept();
InputStream in = s.getInputStream();
byte[] b = new byte[256];
in.read(b);
System.out.write(b);
System.out.flush();
System.out.println("\nReceived");
OutputStream out = s.getOutputStream();
String msg = "Response from server";
byte[] byteMsg = msg.getBytes();
out.write(byteMsg);
out.flush();
out.close();
}
}
클라이언트에서도 서버처럼 InputStream을 이용해서 메세지를 받을 수 있다.
// client
public static void main(String[] args) {
Socket s = new Socket("ip", "port");
OutputStream out = s.getOutputStream();
String msg = "Hello from client";
byte[] byteMsg = msg.getBytes();
out.write(byteMsg);
out.flush();
InputStream in = s.getInputStream();
byte[] b = new byte[256];
in.read(bytes);
System.out.write(b);
System.out.flush();
System.out.println("done");
out.close();
in.close();
s.close();
}
얼마전에 같이 공부하는 친구가 소켓을 한 마디로 표현하면 뭐라고 할 수 있냐는 질문에 답을 하지 못했었는데, 이번에 I/O 사용과 네트워크 공부를 하고나니 설명할 수 있을 것 같다.
우편물을 받을 수 있는 우편함에 비유할 것 같다.
ip = 건물 주소 / port는 건물내의 몇호 인지
다른 컴퓨터와 통신을 할 때는 ip와 port를 이용해서 내 프로그램을 특정한다.
우선 ip를 통해서 내 컴퓨터를 찾는다. 그리고 내 컴퓨터에서 작동하는 많은 프로그램들 중에서 내가 서버 통신을 할 프로그램의 위치를 port로 찾는다.
물론 주소를 특정하는 것 이외에도, I/O Stream을 관리하는 역할을 함께한다!
이번에 내 컴퓨터에 띄워놓은 서버에 같은 LAN에 있는 다른 기기로 접근해보려고 하면서 알게 된 통신방법이다
나는 맥을 사용하고 있기 때문에 터미널에서 아래의 명령어를 사용했다.
$ nc ip port // 서버에 연결하는 코드
$ nc 192.168.0.0 8080 // 예시
서버를 해당 ip에 띄워놓고 위 명령어로 해당 서버에 붙으면 터미널에서 메세지를 보내볼 수 있다.
$ nc -l 8080 // 서버 포트 여는 법
별도로 자바서버를 구현하지 않고, 그냥 터미널에서 위 명령어를 입력한다면
해당 포트로 소켓통신이 가능하게 된다.
ip와 port에 대한 지식이 조금 생기고 나니, 이런 통신이 어떻게 가능한지 조금은 이해가 되는것 같아 보람이 있다.
보내면 항상 같은 메세지가 오는 간단한 형태이지만 socket을 사용해서 통신을 연결하고, I/O Stream을 사용해서 데이터를 주고 받을 수 있는 것을 확인.