studybook
  • Introduction
  • 실무 하며 깨닫는 부분 정리
    • 옵션에 대해서
    • 코드 작성의 순서
    • 자바 프로그램에 문제가 생겼다면
    • 장애 대처법
  • Logstash, Beats 정리
  • Zookeeper 정리
  • Message Queue 정리
    • RabbitMQ 삽질
  • Java 관련 정리
    • Java Primitive Wrapper class
    • Java NIO
    • Java8 Double colon operator
    • Effective Java
      • 4장
      • 5장
      • 6장 - Enum, Annotation
      • 7장 - Method
      • 8장 - 프로그래밍 일반
      • 9장 - Exception
    • Java8 Lambda expression
    • JDBC
    • Linux에서 WatchService 이상동작
  • Spring 관련 정리
    • Spring Bean init, destroy 순서
    • Spring Async Controller
    • Spring Executable jar 웹 개발 및 배포
    • Spring Boot Font 배포 에러
    • Spring AOP
      • Spring AOP로 모든 Request 로그 남기기
    • Spring Cache
    • Spring Cloud
      • Consul로 spring 설정 관리하기
    • Spring Test
      • Spring Test DirtiesContext
      • Spring Test MockBean, SpyBean
      • Spring Test Dynamic @Scheduled
    • Spring JDBC
    • Spring Validation
    • Spring Transaction Management
      • Spring with JTA 삽질
    • Spring에서 효율적으로 Static resource 관리하기
    • Zuul을 사용해서 Spring Reverse proxy 만들기
    • Spring Security
    • 스프링 어노테이션이 안 먹힐 때 의심해볼만한 것
    • Spring Data
    • Spring Webflux
      • Tobi 강연
  • 코드 리팩토링
    • 한번에 하나씩
  • 지속적 통합 (CI)
    • Jenkins pipeline 삽질기
  • Log Aggregator 정리
    • Flume 테스트
    • Fluentd 테스트
  • Web Socket 정리
  • Akka
    • Actor 모델
    • Supervision
  • IE 8 대응 정리
  • 함수형 프로그래밍
    • 모나드
  • Netty
    • Netty 기본 예제
    • Netty 주요 특징
    • Netty 부트스트랩
    • Netty 채널 파이프라인, 코덱
    • Netty 이벤트 모델
    • Netty 바이트 버퍼
  • 스칼라 관련 정리
    • Maven으로 컴파일하기
    • Scala def 괄호 여부의 차이
    • 스칼라 function, method 차이점
    • ScalaTest와 Spring 연동하기
    • Programming in Scala
  • J2S 컨퍼런스
  • Android
    • 테스트
    • NDK
  • DDOS
  • HTTP
  • HttpClient
  • Container
    • Image 개요
    • cri-o
    • kata containers
    • Open Container Initiative Image
    • Buildkit
  • Github pages
  • Static Website
  • Webhook
  • Service Discovery Tools
    • Etcd
    • Eureka
    • Consul
      • ACL
    • 비교
  • React
    • JSX
    • React Element
    • Components, Props
    • State, Lifecycle
    • Handling Event
    • Flux
  • Vagrant
    • SSH 접속
  • Linux
    • Systemd
    • Alternatives
  • Messaging protocols
    • XMPP
    • AMQP
  • Windows
    • Windows10 내장 우분투에 ssh 클라이언트로 접속하기
    • Windows10 Hyper-V와 Virtual Box가 충돌을 일으켰을 때
    • Hyper-V 기반 docker에서 Shared Drives 설정 실패할 때
    • 윈도우 개발환경 설정
    • Docker desktop 없이 docker 환경 세팅하기
    • UWP 앱을 항상 관리자권한으로 실행하는 바로가기 만들기
  • Spring camp 2017
    • Project Reactive
    • 이벤트 소싱
    • CQRS
  • Spring webflux
  • 리액티브 프로그래밍
  • Linux Settings
    • 홈서버 백업 및 복구기
    • 홈서버 트러블슈팅
  • Kubernetes
    • k3s 설치 및 삽질
    • pod resources
    • Argo workflow
    • 트러블 슈팅
      • Kubernetes namespace의 phase가 Terminating에서 멈춰있을 때
    • 쿠버네티스 마스터
    • Knative
    • Knative Pipeline
    • Aggrerated API server
    • Accessing the API
      • Authenticating
  • Sonarqube
  • HTTP/2
  • Go
    • Go Module
    • Go dependency injection
    • Go Error handling
    • Go in Action
      • 3장 패키지
      • 4장 배열, 슬라이스, 맵
      • 5장 GO의 타입 시스템
      • 6장 동시성
      • 7장 동시성 패턴
      • 8장 표준 라이브러리
      • 9장 테스트와 벤치마킹
    • Go Channel 사용법
  • Cloud Native
Powered by GitBook
On this page
  • 테스트 환경
  • Discard 서버
  • Echo 서버, 클라이언트
  • Server
  • Client
  1. Netty

Netty 기본 예제

테스트 환경

  • Java 8

  • Logback

Discard 서버

  • 8888 port를 listen하는 web server. 데이터를 받기만 할 뿐 아무런 동작도 하지 않음.

  • port와 handler를 설정하는 main server

  • client로부터 받은 입력 데이터를 처리하는 handler

  • telnet localhost 8888 명령어로 테스트 가능

public class DiscardServer {
  public static void main(String[] args) throws InterruptedException {
    EventLoopGroup bossGroup = new NioEventLoopGroup(1);
    EventLoopGroup workerGroup = new NioEventLoopGroup();

    try {
      ServerBootstrap bootstrap = new ServerBootstrap();
      bootstrap.group(bossGroup, workerGroup)
          .channel(NioServerSocketChannel.class)
          .childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel socketChannel) throws Exception {
              ChannelPipeline pipeline = socketChannel.pipeline();
              // 핸들러 설정
              pipeline.addLast(new DiscardServerHandler());
            }
          });

      // 포트 지정
      ChannelFuture future = bootstrap.bind(8888).sync();
      future.channel().closeFuture().sync();
    } finally {
      workerGroup.shutdownGracefully();
      bossGroup.shutdownGracefully();
    }
  }
}
public class DiscardServerHandler extends SimpleChannelInboundHandler<Object> {
  private static final Logger logger = LoggerFactory.getLogger(DiscardServerHandler.class);

  @Override
  protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception {
    logger.debug("channelRead0");
  }

  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    logger.error("exceptionCaught", cause);
    ctx.close();
  }
}

Echo 서버, 클라이언트

  • 서버는 입력 받은 메세지를 그대로 다시 클라이언트에게 돌려줌

  • SimpleChannelInboundHandler 대신에 ChannelInboundHandlerAdapter 사용

  • 클라이언트는 채널이 활성화되면 "Hello, Netty!" 메세지를 서버에게 전송

Server

public class EchoServer {
  private static final Logger logger = LoggerFactory.getLogger(EchoServer.class);

  private EventLoopGroup bossGroup;
  private EventLoopGroup workerGroup;
  private ServerBootstrap bootstrap;

  public EchoServer() {
    bossGroup = new NioEventLoopGroup(1);
    workerGroup = new NioEventLoopGroup();

    bootstrap = new ServerBootstrap();
    bootstrap.group(bossGroup, workerGroup)
        .channel(NioServerSocketChannel.class)
        .childHandler(new ChannelInitializer<SocketChannel>() {
          @Override
          protected void initChannel(SocketChannel socketChannel) throws Exception {
            ChannelPipeline pipeline = socketChannel.pipeline();
            // 핸들러 설정
            pipeline.addLast(new EchoServerHandler());
          }
        });
  }

  public void start(final int port) throws InterruptedException {
    logger.info("start server...");
    ChannelFuture future = bootstrap.bind(port).sync();
    future.channel().closeFuture().sync();
  }

  public void close() {
    logger.info("close server...");
    workerGroup.shutdownGracefully();
    bossGroup.shutdownGracefully();
  }
}
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
  private static final Logger logger = LoggerFactory.getLogger(EchoServerHandler.class);

  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    logger.debug("receive message \"{}\"", ((ByteBuf)msg).toString(Charset.defaultCharset()));
    ctx.write(msg); // 버퍼에 쓰기
  }

  @Override
  public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
    ctx.flush(); // 채널 파이프라인에 저장된 버퍼 전송
  }

  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    logger.error("exceptionCaught", cause);
    ctx.close();
  }
}

Client

public class EchoClient {
  private static final Logger logger = LoggerFactory.getLogger(EchoClient.class);

  private EventLoopGroup group;
  private Bootstrap bootstrap;

  public EchoClient() {
    group = new NioEventLoopGroup();

    bootstrap = new Bootstrap();
    bootstrap.group(group)
        .channel(NioSocketChannel.class)
        .handler(new ChannelInitializer<SocketChannel>() {
          protected void initChannel(SocketChannel socketChannel) throws Exception {
            ChannelPipeline pipeline = socketChannel.pipeline();
            pipeline.addLast(new EchoClientHandler());
          }
        });
  }

  public void connect(final String host, final int port) throws InterruptedException {
    logger.info("connect to {}:{}", host, port);
    ChannelFuture future = bootstrap.connect(host, port).sync();
    future.channel().closeFuture().sync();
  }

  public void close() {
    logger.info("close client...");
    if (group != null) {
      group.shutdownGracefully();
    }
  }
}
public class EchoClientHandler extends ChannelInboundHandlerAdapter {
  private static final Logger logger = LoggerFactory.getLogger(EchoClientHandler.class);

  @Override
  public void channelActive(ChannelHandlerContext ctx) throws Exception {
    String sendMessage = "Hello, Netty!";

    ByteBuf messageBuffer = Unpooled.buffer();
    messageBuffer.writeBytes(sendMessage.getBytes());

    ctx.writeAndFlush(messageBuffer);

    if (logger.isDebugEnabled()) {
      logger.debug("send message \"{}\"", sendMessage);
    }
  }

  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    if (logger.isDebugEnabled()) {
      logger.debug("receive message \"{}\"", ((ByteBuf) msg).toString(Charset.defaultCharset()));
    }
  }

  @Override
  public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
    ctx.close();
  }

  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    logger.error("exceptionCaught", cause);
    ctx.close();
  }
}
PreviousNettyNextNetty 주요 특징

Last updated 7 years ago