chapter 8. 소켓 API
Java7의 NIO.2에서 추가된 Socket 관련 기능
- NetworkChannel 인터페이스 도입
- ServerSocketChannel , SocketChannel, DatagramChannel 도입
- SocketOption<T> 인터페이스와 StandardSocketOption을 사용하여 Socket 옵션 설정 및 가져오기
- MulticastChannel 인터페이스 도입
8.1 NetworkChannel 소개
주요 공통 메서드 : bind() , getLocalAddress() ,
주요 메소드
- bind() : 채널의 소켓을 로컬 주소에 바인딩한다. 정확하게 소켓과 로컬 주소 사이에 연관 관계를 설정 한다. null을 전달하면 로컬 주소를 자동으로 할당한다.NetworkChannel bind(SocketAddress local) throws IOException
- getLocalAddress() : 바인딩된 주소를 추출함. 바인딩 되지 않으면 null을 반환 한다.NetworkChannel getLocalAddress() throws IOException
8.1.1 소켓 옵션
소켓과 연관된 옵션은 SocketOption<T> 인터페이스로 표현됨.
StandardSocketOption 클래스에 표준 옵션
- IP_MULTICAST_IF : UDP 멀티캐스트 다이어그램에서 사용되는 NIC를 지정하기 위해서 사용한다. null 값을 지정하면 OS가 자동으로 선택.
- IP_MULTICAST_LOOP : 멀티캐스트 다이어그램의 루프백을 제어하는 하는 boolean 값(기본값 true)
- IP_MULTICAST_TTL : UDP 소켓에서 전송된 멀티캐스트 TTL(time-to-live)값 (범위 0 ~ 255, 기본값 1)
1으로 설정되면 외부 네트워크로 전달되는 것을 방지 한다. - IP_TOS : IP 패킷 안에 정의되는 ToS(Type of Service) 옥텟 값을 나타낸다. IPv4 전용, (기본값 0)
- SO_BROADCAST : 브로드캐스트 데이터그램의 전송 여부를 결정하는 boolean 값(기본값 false)
- SO_KEEPALIVE : 연결 유지 여부를 결정하는 boolean 값 (기본값 false)
- SO_LINGER : 타임아웃 값을 설정(기본값 음수, 즉 비활성화), 블로킹 모드에서 close() 사용해서 중단할 때 전송할 Data가 남아 있으면 주어진 linger interval 만큼 대기 한다.
- SO_RCVBUF : 소켓 수신 버퍼의 크기 (단위 byte) , 기본값을 OS가 지정함. 음수 불가
- SO_SNDBUF : 소켓 송신 버퍼의 크기 (단위 byte) , 기본값을 OS가 지정함. 음수 불가
- SO_REUSEADDR : 주소 재 사용 여부를 나타내는 정수 값. UDP 멀티캐스팅에서 유용, TCP의 경우 TIME_WAIT 상태일 때 주소를 바인딩할 수 있다. 기본값은 OS 마다 틀림.
관련메소드-옵션 가져오기/변경하기
<T> T getOption(SocketOption<T> name) throws IOException
<T> NetworkChannel setOption(SocketOption<T> name,T value) throws IOException
특정 채널에서 지원하는 옵션을 가져오는 메소드
Set<SocketOptions<?>> supportedOptions()
8.2 TCP 서버/클라이언트 애플리케이션 작성하기
8.2.1 블로킹과 논블로킹 메커니즘의 비교
블로킹 혹은 논블로킹 선택 해야 함.
-> 개발자 입장에서 이 두가지 개념을 반드시 이해(복잡도) , 일반적은 논블로킹 성능과 확장성이 블로킹 보다 좋다.
** 그러나 복잡도는 증가한다.
8.2.2 블로킹 TCP 서버 작성하기
블로킹 메커니즘 설정하기 : ServerSocketChannel.configureBlocking(true)
서버 채널 옵션 설정 (아래 두가지를 지원한다.)
serverSocketChannel.setOption(StandardSocketOptions.SO_RCVBUF, 4 * 1024);
serverSocketChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
- IP 주소를 와이들카드(*) 주소를 사용할때 NIC가 여러 개 인 경우 발생할수 충돌을 피해야 하므로 일반적으로 지정된 NIC 주소를 사용하는 것이 좋다.
- 바인딩되지 않은 서버 소켓 채널에 대해 accept() 메소드를 호출하면 NotYetBoundException예외가 발생한다.
- SocketChannel.getRemoteAddress() 이용해서 원격지 주소를 알수 있음(Java7, NIO.2에 추가됨)
I/O를 위한 연결 종료하기
NIO.2의 새 메서드 SocketChannel.shutdownInput(),SocketChannel.shutdownOutput()을 호출해서 채널을 닫지 않아도 I/O를 위한 연결을 종료할 수 있다.
8.2.3 블로킹 TCP 클라이언트 작성하기
소켓 채널 옵션 설정하기
지원하는 옵션들
- SO_RCVBUF
- SO_LINGER
- IP_TOS
- SO_OOBINLINE
- SO_REUSEADDR
- TCP_NODELAY
- SO_KEEPALIVE
- SO_SNDBUF
8.2.4 블로킹 에코 애플리케이션 테스트 하기
8.2.5 논블로킹 TCP 클라이언트/서버 애플리케이션 작성하기
논블로킹 I/O - 채널을 사용하는 프로세스를 블로킹하지 않고 작업함.
java.nio.channels.Selector의 특징
- 엔티티일때 복잡해짐.(즉 java.nio.channels.Selector 클래스 사용할 때)
- Selector는 open() 메소드로 생성한다.
- Selector는 데이터 전송을 위해 하나 이상의 채널을 이용할 수 있고 각각의 기록된 소켓 채널을 모니터링 함.
- 다중 소켓의 IO 읽기/쓰기 작업을 하나의 쓰레드에서 처리할 수있다.(멀티프렉싱 개념 덕분)
- java.nio.channels.SelectableChannels를 위한 멀티플렉서
- ServerSocketChannel와 SocketChannel의 register()를 통해 등록할 수 있음.
- 셀렉터에 의해 채널에 할당된 리소스를 해제해서 등록을 해지 할 수 있음.
SelectionKey 클래스 : 채널이 Selector로 등록할 때 마다 생성되는 구분 클래스, 클라이언트와 요청 유형(연결,읽기,쓰기)을 식별하는 정보가 들어 있다.
동작 정보 유형
- SelectionKey.OP_ACCEPT(수락기능) : 클라이언트가 연결 요청(보통 서버측에서 생성)
- SelectionKey.OP_CONNECT(연결기능) : 서버가 연결을 수락(보통 클라이언트 측에서 생성)
- SelectionKey.OP_READ(읽기기능) : 읽기 동작
- SelectionKey.OP_WRITE(쓰기기능) : 쓰기 동작
Selector 관리하는 세가지 키 집합
- key-set : 등록된 키 집합
- selected-key : 선택된 키 집합. 하나 이상의 연산을 탐지할 준비가 된 각 키 집합.
- cancelled-key : 취소된 키 집합, 키를 취소했지만 아직 등록이 해지되지 않는 키 집합.
** 논블로킹 모드에서 I/O 연산은 요청한 것보다 적은 바이트(분활 읽기/쓰기)를 전송하거나 바이트를 전혀 전송하지 않을수 있다.
셀렉터 기반의 논블로킹의 흐름도
Selector 메소드
- open() : 새 셀렉터를 생성한다.
- select() : 블로킹 선택 작업을 수행해서 키의 집합을 선택한다.
- select(t) : select()와 동일 지저된 시간동안만 블로킹 한다.
- selectNow() : select()와 동일 논블로킹 선택 작업을 수행
- selectedKeys() : 셀렉터가 선택한 키 집합을 Set<SelectionKey>로 반환한다.
- keys() : 셀렉터의 키 집합을 반환한댜.
- wakeup() : 아직 반환되지 않는 첫 번째 선택 작업이 즉시 반환하게 한다.
SelectionKey 메소드
- isValid() : 키가 유효한지 확인 한다. 키가 취소되거나 키의 채널이 닫혔거나 키의 셀렉터가 닫혔다면 키는 유효하지 않다.
- isReadable(): 키의 채널을 읽을 수 있는지 검사
- isWritable() : 키의 채널을 쓸수 있는지 검사
- isAcceptable() : 키의 채널이 새 소켓 연결을 수락할 수 있는지 검사
- isConnectable() : 채널의 소켓 연결 작업을 종료하기 위해 키의 채널이 끝났거나 실패했는지 검사
- cancel() : 셀렉터의 등록 취소를 요청
- interestOps() : 키의 interest set를 가져 온다.
- interestOps(t) : 키의 interest set을 주어진 값으로 설정한다.
- readyOps() : 키의 준비된 작업 집합을 가져온다.
그외 메소드
register() : ServerSocketChannel 혹은 SocketChannel 있는 메소드, 주어진 셀렉터를 현재 채널에 등록하고 셀렉션 키를 반환하는 용도로 쓰임.
public final SelectionKey register(Selector s,int p,Object a) throws ClosedChannelException
8.3 UDP 서버/클라이언트 애플리케이션 작성하기
UDP의 두 가지 중요한 특징
- IP 패킷 하나에 담을 수 있는 양에 따라 패킷 크기가 제한 된다는 점.(최대 크기 65507 byte - 원래는 65535 여기서 IP 헤더 크기 20 byte 와 UDP 헤더 8 byte 뺀값)
- 데이터의 특정 순서로 전송하는 것을 보장하지 않는다, 전송된 데이터가 도착한다는 보장도 하지 않는다.
각 패킷은 IP 주소와 포트를 캡슐화 한다.(TCP 전화, UDP 편지)
8.3.1 UDP 서버 작성하기
java.nio.channels.DatagramChannel - 주요 관련 클래스
java.net.StandardProtocolFamily ( 프로토콜 패밀리 매개변수 , DatagramChannel.open() 매개변수)
- StandardProtocolFamily.INET : IP 버전 4(IPv4)
- StandardProtocolFamily.INET6 : IP 버전 6(IPv6)
DatagramChannel이 지원하는 소켓 옵션들
- SO_REUSEADDR
- SO_BROADCAST
- IP_MULTICAST_LOOP
- SO_SNDBUF
- IP_MULTICAST_TTL
- IP_MULTICAST_IF
- SO_RCVBUF
DatagramChannel 주요 메소드
- open() : 소켓 생성
- isOpen() : 소켓 채널이 성공적으로 열렸는지
- supportedOptions() : 지원하는 소켓 옵션 알아내기
- bind() : 로컬 주소에 바인딩하고 소켓이 연결 요청에 대기하도록 함.
- send() : 메시지 전송
- receive() 메시지 받기
- getRemoteAddress() : 원격지 주소 얻기
- close() : 채널 닫기
8.3.2 비연결지향 UDP 클라이언트 작성하기
서버 작성와 비슷하다. send(),receive() 사용
8.3.4 연결지향 UDP 클라이언트 작성하기
read()와 write()를 사용함. 고정된 원격지 주소와 통신을 한다. 즉 만약 다른 쪽과 통신을 하고 싶다면 연결을 해지 않고 재 연결해야 한다.
- DatagramChannel.connect() : 명시적으로 호출해야 함. - 연결할 주소지 정보를 전달해야 함.
- DatagramChannel.isConnected() : 연결 상태를 확인 할 수 있다.
8.3.6 멀티캐스팅
테이터그램 수신자로 표현되는 그룹이라는 표기법을 사용함. 그룹은 클래스D IP 주소로 식별한다.
** 클래스D 영역(IPv4 기준 : 224.0.0.1 ~ 239.255.255.255 사이) 새 수신자(클라이언트)가 멀티캐스트 그룹에 가입하려면 그에 상응하는 IP 주소를 통해 그룹에 연결해야 하며, 들어오는 데이터그램을 리스닝해야 한다.
java.nio.channels.MulticastChannel
- NIO.2에서 추가됨
- IP 멀티 캐스팅을 지원하는 네트워크 채널을 매핑하는 새로운 인터페이스를 제공
- NetworkChannel의 서브인터페이스 이고 DatagramChannel 클래스에서만 구현되어 있음.
- 주요 메소드
- join() : MemberShipKey를 리턴값으로 받고 아래 두 가지 형태 메소드가 있다.
- join(InetAddress g, NetworkInterface i) : 정보를 받기 위해서 멀티캐스트 그룹에 가입하는 것
- joni(InetAddress g, NetworkInterface i, InetAddress s) : 그룹에 가입한다. s - 메시지를 받을 수 있는 출발지 주소를 알려준다.
- close() : membership을 버리고 채널을 닫는데 사용된다.
- ** 멀티캐스트 채널은 여러 그룹 가입 가능, 여러 인터페이스에 동일한 그룹 가입 가능
java.nio.channels.MemberShipKey
- IP 멀티캐스 그룹의 회원 구분자(토근)
- 자주 하는 동작
- 차단/차단 해제 : block()/unblock() , 특정 주소 메시지 차단/해지
- 그룹 가져오기 : group() ,리턴 유형은 InetAddress
- 채널 가져오기 : channel(), 리턴 유형은 MulticastChannel
- 출발지 주소 가져오기 : 출발지 주소가 정해져 있다면 , sourceAddress(), 리턴 유형은 InetAddress
- 네트워크 인터페이스 가져오기 : networkInterface() , 리턴 유형은 NetworkInterface
- 유효성 검사 : isValid()
- 버리기 : drop()
NetworkInterface 소개
NIC에 할당된 IP 주소의 목록과 이름으로 구성된 정보를 표현 (즉 네트워크 카드 정보를 알아낼 수 있다)
댓글 없음:
댓글 쓰기