2013-01-08 5 views
54

일반적으로 SocketChannelsNIO을 이해하려고합니다. 정규 소켓으로 작업하는 방법과 클라이언트 당 간단한 스레드 (일반적인 블로킹 소켓 사용)를 만드는 방법을 알고 있습니다.소켓 대 소켓 소켓

그래서 내 질문 :

  • SocketChannel에 무엇인가?
  • Socket 대신 SocketChannel을 사용할 때 얻을 수있는 여분은 무엇입니까?
  • 채널과 버퍼의 관계는 무엇입니까?
  • 선택기 란 무엇입니까?
  • documentation의 첫 번째 문장은 A selectable channel for stream-oriented connecting sockets.입니다. 그게 무슨 뜻 이죠?

나는 또한 this documentation을 읽고,하지만 어떻게 든 나는 Socket가 차단 입력/출력 장치입니다 ...

+5

배경이 아닌 내용 때문에 질문을 downvoted 다른 사람을 사과해야합니다. 동료 대학원생으로서, 특히 귀하의 연구 분야에 정확히 속하지 않은 과정을 강요 할 때, 특히 귀하의 연구비가 연구 분야에 달려있을 때 특히 그렇습니다. 나는 당신이 여기에 와서 해명을 구하는 것도 좋다고 생각합니다. –

답변

45

그것을 받고 있지 않다. 그것은 Thread을 사용하여 읽기를 차단하고 기본 버퍼가 꽉 찬 경우 쓰기를 차단할 수도 있습니다. 따라서 서버에 열린 Socket 개가있는 경우 여러 스레드를 만들어야합니다.

SocketChannel은 소켓에서 읽을 수있는 비 블로킹 방식이므로 하나의 스레드가 여러 개의 열린 연결과 동시에 통신 할 수 있습니다. 이것은 SelectorSocketChannel을 추가 한 다음 선택기의 select() 메소드에서 반복합니다.이 메소드는 소켓이 수락되었거나 데이터가 수신되거나 닫힌 경우 사용자에게 알릴 수 있습니다. 이를 통해 하나의 스레드에서 여러 클라이언트와 통신 할 수 있으며 여러 스레드 및 동기화의 오버 헤드가 발생하지 않습니다.

Buffer은 데이터를 새로운 어레이로 복사하는 오버 헤드를 피하기 위해 읽기 및 쓰기에서 기본 데이터에 액세스 할 수있게 해주는 NIO의 또 다른 기능입니다.

+0

대단히 감사합니다. 그러나 나는 아직도 놓친 점이있다. 선택기없이 채널을 사용하면 어떤 이점이 있습니까? 또는 그들은 함께 모이는가? –

+1

선택기가 없으면 채널을 사용할 수 없습니다. 예를 들어 채널을 읽을 준비가되면 선택기가 알려주기 때문입니다. 기본적으로 선택기의 기능을 다시 구현할 때 채널 자체를 사용하려는 이유를 생각할 수 없습니다. –

+1

실례지만, SocketChannel non-blocking은 어떤 방식으로 작동합니까? Selector.select()는 * 차단 * 작업입니다. 당신은 select()가 알려주지 만, 실제로는 단순히 차단합니다. 이것은 콜백을 사용하지 않기 때문에 알림이라고 부를 수 없습니다. – ZhekaKozlov

16

지금까지 NIO은 너무 오래되어서 Java가 1.4 이전에 어떤 것인지 기억하지 못합니다. 이는 ""의 이유를 이해하기 위해 알아야 할 사항입니다.

Java 1.3까지 모든 입출력은 차단 유형이었습니다. 그리고 더 나쁜 것은 멀티 플렉스 I/O에 대한 시스템 호출 select()의 아날로그가 없었습니다. 결과적으로 Java로 구현 된 서버는 "연결 당 1 스레드 (one-thread-per-connection)"서비스 전략을 채택 할 수 밖에 없었습니다.

Java 1.4에서 소개 된 NIO의 기본 요점은 전통적인 UNIX 스타일의 다중 비 차단 I/O 기능을 Java에서 사용할 수있게하는 것이 었습니다. select() 또는 poll()을 사용하여 파일 설명자 (소켓)에 대한 I/O 준비를 감지하는 방법을 이해하면 NIO에 필요한 서비스를 찾을 수 있습니다. 비 차단에 SocketChannel을 사용합니다 입출력 엔드 포인트, fdsets 또는 pollfd 어레이의 경우 Selector입니다. 스레드 풀이있는 서버 또는 둘 이상의 연결을 각각 처리하는 스레드가 이제 가능 해졌습니다. 그것은 "여분"입니다.

Buffer은 비 블로킹 소켓 I/O에 필요한 바이트 배열의 종류이며, 특히 출력/쓰기면에 있습니다. 블로킹 I/O를 사용하여 버퍼의 일부만 즉시 쓰면 전체 스레드가 기록 될 때까지 스레드가 차단됩니다.비 블로킹 I/O를 사용하면 쓰레드는 쓰여진 금액의 반환 값을 얻고, 다음 라운드에서 남은 일을 처리하기 위해 남겨 둡니다. Buffer은 채우기 및 배수를 위해 생산자/소비자 패턴을 명시 적으로 구현하여 이러한 기계적인 세부 사항을 처리합니다. 스레드와 JVM의 커널은 이 아니며이 동기화됩니다.

+0

'SocketChannel'이 (가) 차단 중입니다. 최소한'read()'와'write()'메소드는 있습니다. 진정한 non-blocking 채널은 자바 7에서 소개 된'AsynchronousSocketChannel'입니다. – ZhekaKozlov

+2

정말요? 그렇다면 Java 1.4에서 NIO가 도입 된 이후로 있었던 configureBlocking (bool) 메소드는 어떻게 되었을까요? – arayq2

+0

하지만 바이트를 사용할 수있게 되 자마자 읽을 필요가 있다면 어떻게해야할까요? 이 경우 일부 차단 작업을 호출해야합니다. – ZhekaKozlov

4

SocketChannels을 사용하고 있더라도 channels을 처리하려면 스레드 풀을 사용해야합니다.

둘 다 폴링 select()에 대한 책임이 오직 하나 개의 스레드를 사용하는 scenairo에 대해 생각하고 처리하는 것은 SocketChannels 한 채널 처리 1 초 정도 소요되며, 큐에 10 개 채널이있는 경우, Selectors에서 선택, 당신이에 의미 다음 폴링 전에 10 초를 기다려야합니다. 따라서 채널 처리를위한 스레드 풀이 있어야합니다.

이 의미에서 나는 클라이언트 당 스레드 차단 소켓 패턴에 엄청난 차이점을 보지 못했습니다. 주요 차이점은 NIO 패턴이며, 작업은 더 작고, 작업 당 스레드와 비슷하며, 작업을 읽고, 쓰고, 프로세스 등을 자세히 처리 할 수 ​​있습니다. Netty의 구현 NioServerSocketChannelFactory, 하나의 Boss 스레드가 연결을 허용하고 처리를 위해 Worker 스레드 풀에 작업을 디스패치합니다.

정말 한 스레드에서 멋지다면 최소한 I/O 풀링을해야합니다. 스레드는 입출력 작업이 종종 명령 처리주기보다 느리기 때문에 귀중한 하나의 스레드가 입출력에 의해 차단되는 것을 원하지 않으며 정확하게 NodeJS 한 스레드 수신 연결을 사용하고 모든 I/O는 비동기이며 병렬 처리됩니다. 백엔드 I/O 스레드 풀에 의해 중단됩니다.

은 이전 스타일의 스레드 당 클라이언트가 죽었습니까? NIO 프로그래밍이 복잡하고 멀티 스레드가 자연스럽지 않은 것은 아닙니다. 최신 운영 체제와 CPU가 멀티 태스킹에서 더 좋아지고 개선됨에 유의하십시오. 따라서 멀티 스레딩의 오버 헤드가 시간이 지남에 따라 줄어 듭니다.

+0

한 채널에서 처리하는 데 1 초가 걸리면 NIO를 사용하면 안됩니다. – John

+0

@ 존 당신은 그 때 무엇을 사용하고 있습니까? –