Java Network

Moom2n·2024년 3월 20일
0

Java

목록 보기
23/26

Socket

- Socket 이란?

일반적으로 socket(소켓) 통신에서의 socket은 network상에서 사용되는 network socket을 말한다

  • Network를 통해 데이터를 주고 받기 위한 endpoint(엔드포인트)
    -- 서비스별로 엔드포인트가 존재하고, 해당 서비스 통신을 위해서는 해당 엔드포인트에 연결

  • Internet Socket
    -- Protocol(프로토콜), IP address(IP 주소), port number(포트)로 정의됨
    -- Protocol: 다른 시스템과 원활한 통신을 위한 통신 규약
    -- IP address: Internet Protcol 통신을 위한 고유 식별 번호
    -- Port number: 각 host별로 특정 서비스를 위해 지정되고, 네트워크 통신에서 특정 서비스 연결을 위해 사용되는 값으로 단일 host내에서 서로 다른 서비스간 공유할 수 없다.

  • 특정 port 번호를 같는 socket은 잘 알려진 서비스와 연관됨
    -- 80: HTTP
    -- 22: ssh
    -- 443: HTTPS

  • 잘 알려진 서비스를 특정 port 번호외 다른 port 번호로 변경 가능
    -- 특별한 목적으로 web service를 80이 아닌 8080으로 설정 가능

- Socket Type

Datagram Sockets

  • UDP(User Datagram Protocol)를 사용하는 무연결 socket (단방향 연결)
    -- Ex). 영상 공유

  • Datagram socket에서 보내거나 받은 packet은 개별적으로 주소가 지정되고 라우팅됨

  • Datagram socket에서는 순서와 신뢰성이 보장되지 않으므로 한 기계 또는 프로세스에서 다른 기계로 전송되는 여러 packet이 임의의 순서로 도착하거나 전혀 도착하지 않을 수 있음

Stream Sockets

  • Connection-oriented Sockets
    -- TCP(Transmission Control Protocol)
    -- SCTP(Stream Control Transmission Protocol)
    -- DCCP(Datagram Congestion Control Protocol)

  • 오류 없는 데이터 전송, packet 순서, 흐름 제어 보장

  • 인터넷에서 일반적으로 TCP를 사용하여 구현
    -- Application에서 TCP/IP 프로토콜을 사용하여 통신

  • 송신된 순서에 따라 중복되지 않게 데이터를 수신함으로 이에 따른 overhead 발생

Raw Sockets

  • 프로토콜별 전송 계층 형식 없이 IP packet을 직접 보내고 받을 수 있음

  • 전송 계층 프로토콜(예: TCP, UDP)에 상관없이 IP packet으로 주고 받음

  • Berkeley sockets을 기반으로 하는 API는 raw sockets을 지원하며, 윈도우 XP는 2001년 윈삭 인터페이스에 구현된 raw sockets 지원을 통해 출시되었으나, 3년 후 마이크로소프트는 보안상의 문제로 row sockets 지원을 제한

  • Nmap과 같은 보안 관련 응용 프로그램에서 사용

  • 일반적으로 네트워크 장비에서 사용할 수 있으며 IGMP와 OSPF와 같은 라우팅 프로토콜에 사용

  • ping 유틸리티에 의해 사용되는 인터넷 제어 메시지 프로토콜(ICMP)에도 사용

- Socket Communication

Socket Communication(통신)은 아래 그림과 같은 흐름을 갖는다.

  • server와 client 필요

  • 다중 접속을 허용할 경우에는 개별 접속마다 별도의 통신 관리 필요

Server Socket

Server socket은 client socket의 연결 요청을 대기하고, 연결 요청이 오면 client socket을 생성하여 통신이 가능하도록 제공한다. send()/recv() + close()

Server socket의 동작 과정은 다음과 같다.

  • socket() 함수를 이용하여 소켓 생성

  • bind() 함수를 이용해 대기 소켓의 IP 주소와 port를 설정

  • listen() 함수로 클라이언트 소켓 연결 요청 대기

  • Client socket 연결 요청이 오면 accept() 함수를 이용해 연결을 승인하고, 요청은 client socket과 통신을 위한 소켓을 생성

  • Server socket은 listen() 함수를 통해 추가적인 연결 요청에 대비하고, 생성된 socket은 연결된 client socket과 데이터를 주고받음

  • Client socket이나 생성된 socket을 닫으면 연결되어 있던 상대 socket도 닫힘

Client Socket

Client socket은 client 프로그램이나 server에서 생성할 수 있다. 위 server socket 설명에서 accept 후 새로운 socket이 생성되는데 이 또한 client socket으로 실질적인 socket 간 통신은 client socket 간에 이루어진다.

Client socket의 동작 과정은 다음과 같다.

  • socket() 함수를 이용하여 socket 생성

  • connect() 함수를 이용해 지정된 sever에 연결 요청 전송

  • Server에서 연결을 받아들이면 데이터 송수신 시작

  • 데이터 송수신이 완료되거나 상대 socket의 닫힘이 감지되면 socket을 닫음


Java Socket Communication

Java에서는 socket 통신을 위해 Socket class와 서버 구성을 위한 ServerSocket class를 지원하며, 아래와 같이 동작한다.

- Class Socket

Socket 생성과 함께 server 연결에 연결 요청을 한다. 이를 위해 Socket constructor에는 연결을 위한 server 정보가 제공 되어야 한다.

Socket socket = new Socket(hostIp, port)

nc -l 12345

import java.io.IOException;
import java.net.Socket;

public class Exam01 {
    public static void main(String[] args) {
        // tag::createSocket[]
        try {
            Socket socket = new Socket("localhost", 12345);
            System.out.println("서버에 연결되었습니다.");

            socket.close();
        } catch (IOException e) {
            System.err.println(e);
        }
        // end::createSocket[]
    }
}

정보 얻기

데이터 보내기

import java.net.Socket;
import java.util.*;

public class Exam02 {
    public static void main(String[] args) {
        String host = "localhost";
        int port = 12345;

        try(Socket socket = new Socket(host, port)) {
            System.out.println("서버 연결 성공");
            Scanner sc = new Scanner(System.in);
            String tmp = "";
            while(!tmp.equals("exit\n")) {
               tmp = sc.nextLine() + "\n";
               socket.getOutputStream().write(tmp.getBytes());
            }
            sc.close();
        } catch(Exception e) {
            System.err.println(host + ":" + port + "에 연결 불가");
        }
    }
}

실행결과

데이터 받기

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

public class Quiz05 {
    public static void main(String[] args) {
        String host = "localhost";
        int port = 12345;

        if (args.length > 0) {
            host = args[0];
        }

        try {
            if (args.length > 1) {
                port = Integer.parseInt(args[1]);
            }
        } catch (NumberFormatException ignore) {
            System.err.println("Port가 올바르지 않습니다.");
            System.exit(1);
        }

        try {

            Socket socket = new Socket(host, port);
            System.out.println("서버에 연결되었습니다.");

            String line;

            BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            while(!(line = input.readLine()).equals("exit")) {
                System.out.println(line);
            }

            socket.close();
        } catch (IOException e) {
            System.err.println(e);
        }
    }
}

실행결과

Echo server

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

public class Quiz06 {
    public static void main(String[] args) {
        String host = "localhost";
        int port = 12345;

        try {
            Socket socket = new Socket(host, port);
            System.out.println("서버에 연결되었습니다.");

            String line;

            BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            while(!(line = input.readLine()).equals("exit")) {
                System.out.println(line);
                socket.getOutputStream().write(line.getBytes());
                socket.getOutputStream().write("\n".getBytes());
            }

            socket.close();
        } catch (IOException e) {
            System.err.println(e);
        }
    }
}

실행결과

- 비동기 통신 만들기

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class Quiz07 {
    static class Receiver extends Thread {
        BufferedReader input;

        public Receiver(BufferedReader input) {
            this.input = input;
        }

        @Override
        public void run() {
            char[] buffer = new char[2048];

            try {
                while (!Thread.currentThread().isInterrupted()) {
                    int length;
                    length = input.read(buffer);
                    System.out.println("서버에서 보낸 메시지 : " + new String(buffer, 0, length));
                }
            } catch (IOException ignore) {
                //
            }
        }
    }

    public static void main(String[] args) {
        String host = "localhost";
        int port = 12345;

        if (args.length > 0) {
            host = args[0];
        }

        try {
            if (args.length > 1) {
                port = Integer.parseInt(args[1]);
            }
        } catch (NumberFormatException ignore) {
            System.err.println("Port가 올바르지 않습니다.");
            System.exit(1);
        }

        try (Socket socket = new Socket(host, port);
                BufferedReader terminalIn = new BufferedReader(new InputStreamReader(System.in));      // InputStreamReader 가 stream 의 byte 를 reader의 char 로 변환
                BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                BufferedWriter output = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))) {     // OutputStreamWriter 가 stream 의 byte 를 writer 의 char 로 변환
            System.out.println("서버에 연결되었습니다.");

            Receiver receiver = new Receiver(input);

            receiver.start();

            String line;
            while ((line = terminalIn.readLine()) != null) {
                if (line.trim().equals("exit")) {
                    break;
                }
                output.write(line);
                output.flush();
            }

        } catch (IOException e) {
            System.err.println(e);
        }
    }
}

실행결과

로컬 컴퓨터에서 exit 를 입력해야만 프로그램이 종료한다.


0개의 댓글

관련 채용 정보