이번엔 netty 를 코어로 만든 vertx http 서버와 tcp 서버를 만들어보자

필자가 원하는건 이거였다.
http로 날리면 tcp로 푸시를 해주는 그런 서버?
그러기 위해서는 http서버와 tcp 서버를 만들어줘야된다.

vertx 3.x 에는 Router로 수정되었다.
그리고 BusModBase이 아닌 AbstractVerticle 를 상속받아 구현해야 된다. 소스를 보자

public class VerticleProducer extends AbstractVerticle {

  @Override
  public void start() throws Exception {

    Router router = Router.router(vertx);
    router.route().handler(BodyHandler.create());

    router.get("/").handler(this::getOk);
    vertx.createHttpServer().requestHandler(router::accept).listen(8080);
  }

  private void getOk(RoutingContext routingContext) {
    HttpServerResponse response = routingContext.response();
    MultiMap params = routingContext.request().params();
    String id = params.get("id");
    JsonObject code = new JsonObject().put("code", "000").put("id", id);
    response.putHeader("content-type", "application/json").end(code.toString());
  }
}

간단한 http 서버다. 루트로 접속을 하면 그냥 json으로 리턴하는 코드이다.
하지만 필자는 tcp로 푸시를 줘야되는데..
그러기 위해선 eventBus를 사용해야 된다.

routingContext.vertx().eventBus().publish("tcp.push.message", code);

eventBus에는 publish와 send가 있는데 차이점은 모두 주냐 한개만 주냐이다.
publish는 해당 주소에 모두 전달하지만 send는 특정 한개만 전달한다. 그 기준은 잘모르겠다. 먼저 등록되는 놈?

그럼 이제 tcp로 전달해주는 소스를 보자

public class VerticleConsumer extends AbstractVerticle {

  private NetServer server;
  private Map<String, NetSocket> userInfo = new HashMap<>();

  @Override
  public void start() throws Exception {
    server = vertx.createNetServer();

    server.connectHandler(socket ->
      socket.handler(buffer -> userInfo.put(buffer.toString(Charset.defaultCharset()).replaceAll("(\r)?\n", ""), socket))
    );

    server.close(socket -> userInfo.remove(socket));

    EventBus eventBus = vertx.eventBus();

    eventBus.consumer("tcp.push.message", message -> {
      JsonObject body = (JsonObject) message.body();
      NetSocket socket = userInfo.get(body.getString("id"));
      socket.write(body.toString());
    });
    server.listen(8888);
  }
}

보면 일단 tcp로 연결된 아이가 있어야된다.
먼저 연결 한 후에 id를 넘겨야 되는데 클라이언트와 잘맞춰서 해야된다.
consumer는 원래 registerHandler 이거 였다 3.x 로 가면서 변경 되었다.

그럼 테스트를 해보자
서버를 돌린 후에 telnet으로 접속하자

telnet localhost 8888

접속이 되면 임의의 아이디를 넣자.
wonwoo라 넣었다 필자는
그러고 나서 http 서버로 접속을 해보자

http://localhost:8080?id=wonwoo

그러면 telnet에 푸시가 갈 것이다.
잘 작동한다. push서버가 만들어졌다.ㅎㅎㅎ

이 예제는 GitHub에 올라가 있다.