java Socket 으로 알아보는 네트워크

2jun0·2022년 10월 1일
0

자바도 익히고 네트워크도 익힐겸 socket으로 네트워크 동작을 알아보려고 한다.

Socket is a file, Everything is a file

소켓은 데이터를 주고 받기 위한 일종의 터널이다.

포트만 중복되지 않는다면 여러개의 소켓을 동시에 열어 둘 수 있다.
소켓은 OS 단에서 만들어 주는 것으로, 아래의 과정을 거치게 된다.


이미지 출처 : https://recipes4dev.tistory.com/153


이해를 위해 서버 소켓을 생성한다고 하자

서버 소켓은 socket()으로 생성하고 나면, bind()를 이용해 포트번호와 주소를 지정해야 한다.
그 후, listen()으로 클라이언트의 연결을 기다리고 accept()으로 클라이언트 소켓을 생성하는 일을 한다.

그뿐이다, 데이터 송신, 수신과 같은 역할은 서버 소켓이 하지 않는다.
서버 소켓은 시작은 있지만, 끝이 없는 터널과 같아서 데이터를 주고 받지 않는다.

그럼 누가 송수신을 할까?
accept()로 만든 클라이언트 소켓으로 송수신을 한다.

클라이언트 소켓은 시작[서버] <-> 끝[클라이언트]로 이루어져 있다.


데이터 송수신은 마치 파일 입출력처럼 한다.

리눅스 기준으로 소켓은 파일이다. 사실 리눅스에선 소켓과 같은 여러 기능(파이프라인 같은것) 들을 파일로 처리한다.

그래서 자바에서도 InputStream을 이용해서 데이터를 주고 받을 수 있다.

간단한 예제 1

ServerSocket만 가지고 서버 소켓을 여는 예제를 돌려보자.

class Scratch {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(6000);

        Socket serverToClientSocket = serverSocket.accept();
        System.out.println("serverToClientSocket.getLocalPort() = " + serverToClientSocket.getLocalPort());
        System.out.println("serverToClientSocket.getPort() = " + serverToClientSocket.getPort());
    }
}

서버는 6000번 포트로 소켓을 열어 두엇다.

서버가 실행되면 터미널로 telnet 127.0.0.1 6000를 실행하면 방금 열었던 6000번 포트로 통신을 시도한다.

위의 예제에서 서버가 보내는 것은 아무것도 없기 때문에, 터미널에선 아무것도 안보인다.
서버 프로그램에선 아래와 같은 출력이 생기게 된다.

serverToClientSocket.getLocalPort() = 6000
serverToClientSocket.getPort() = 1041

Process finished with exit code 0

serverToClientSocket은 서버에서 클라이언트로 가는 소켓이다.
그래서 getLocalPort()는 서버의 포트번호, getPort()는 클라이언트의 포트번호를 반환한다.

여기서 1041라는 포트번호는 터미널에서 telnet으로 서버에 연결할때 생성한 소켓의 포트번호다.

처음 보고 필자도 뭐지? 터미널에서 1041라는 포트를 지정한 적이 없는데요? 라는 생각이 들었다.
이건 OS에서 임의로 생성해준다고 한다.

간단한 예제 2

이제 ServerSocket에서 데이터를 받아오자.

class Scratch {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(6000);

        Socket serverToClientSocket = serverSocket.accept();
        System.out.println("serverToClientSocket.getLocalPort() = " + clientSocket.getLocalPort());
        System.out.println("serverToClientSocket.getPort() = " + clientSocket.getPort());

        BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        String line = reader.readLine();
        System.out.println("input = " + line);
    }
}

예제1 에서 했던 것과 같이 telnet 127.0.0.1 6000을 실행한 후, hihi를 입력해주었다.

프로그램에는 아래와 같은 출력이 생긴다.

serverToClientSocket.getLocalPort() = 6000
serverToClientSocket.getPort() = 1229
input = hihi

Process finished with exit code 0

텔넷에서 보낸 데이터가 실제로 화면에 보이는 것을 볼 수 있다!

같이 보면 좋은 것들

서블릿 https://pangtrue.tistory.com/55

profile
끄적끄적

0개의 댓글