TCP

gradle
repositories {
    maven { url 'https://repo.spring.io/milestone' }
    mavenCentral()
}

dependencies {
    testImplementation 'org.jetbrains.kotlin:kotlin-test'
    implementation platform('io.projectreactor:reactor-bom:2020.0.24')
    implementation 'io.projectreactor.netty:reactor-netty-core'
    implementation 'io.projectreactor.netty:reactor-netty-http'
}

Server

Execute

์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” TcpServer๋ฅผ ์ด์šฉํ•˜์—ฌ ์ƒ์„ฑํ•ด์ค€๋‹ค.

import io.netty.channel.ChannelOption
import reactor.netty.tcp.TcpServer

val server:DisposableServer = TcpServer.create()
    .host("localhost")
    .port(9988)
    .bindNow()
    
server.onDispose()
      .block()

Handle

๋“ค์–ด์˜จ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด์„  handle์˜ inbound, outbound๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ

.handle { inbound, outbound ->
    outbound.sendString(Mono.just("hello"))
    inbound.receive()
        .asString()
        .doOnNext { println(it) }
        .then()
}

Inbound ๋œ ์š”์ฒญ์„ console๋กœ ์ฐ๊ณ , Hello๋ผ๋Š” ์‘๋‹ต์„ ๋‚ด๋ ค์ฃผ๋Š” handler์ด๋‹ค.

Interceptor

์—ฐ๊ฒฐ์˜ Lifecycle์„ ํ™œ์šฉํ•˜์—ฌ ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

TcpServer.create()
    .doOnBind { println("Bind :: ${it.bindAddress()}") }
    .doOnConnection { println("Connected :: ${it.address()}")  }
    .doOnBound { println("Bound :: ${it.address()}") }
    .doOnUnbound { println("Unbound :: ${it.address()}") }
    .bindNow()
    .onDispose()
    .block()
    
> Bind :: localhost/<unresolved>:9988
> Bound :: /127.0.0.1:9988

Option

์ƒ์„ธoption์„ ์ง€์ •ํ•ด ์ค„์ˆ˜ ์žˆ์œผ๋ฉฐ ์ƒ์„ธ ์˜ต์…˜์€ ๋งํฌ๋ฅผ ์ฐธ์กฐ .option({OPTION}, {VALUE}) ๋กœ ์ง€์ •ํ•  ์ˆ˜์žˆ๋‹ค

Logger

Peer๋“ค๊ฐ„ ํŠธ๋ž˜ํ”ฝ์„ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•œ ๋กœ๊น…์€ .wiretap(true) ๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค

Event Loop

Drawing

์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” Netty์˜ ํ•ต์‹ฌ ์š”์†Œ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” Netty์˜ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๋ฐ ๋‹ค์ค‘ ์Šค๋ ˆ๋“œ ๋ชจ๋ธ์˜ ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค.

์ด ์“ฐ๋ ˆ๋“œ๋Š” ์ด๋ฒคํŠธ ๋ฃจํ”„ ์Šค๋ ˆ๋“œ๋ผ๊ณ ๋„ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ๋„คํŠธ์›Œํฌ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ์ฒ˜๋ฆฌ๋œ ์ด๋ฒคํŠธ๋ฅผ ํ•ด๋‹น ์ฑ„๋„ ํ•ธ๋“ค๋Ÿฌ๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ๋˜ํ•œ ๋‹ค๋ฅธ ์“ฐ๋ ˆ๋“œ์—์„œ ๋ฐœ์ƒํ•œ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ๋ฌดํ•œ ๋ฃจํ”„๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์ฑ„๋„์— ๋Œ€ํ•œ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ์ด๋ฒคํŠธ ํ๋ฅผ ์œ ์ง€ํ•˜๊ณ  ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค ์ด๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ๋˜ํ•œ ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ์˜ ์ˆ˜๋ช… ์ฃผ๊ธฐ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

Netty์˜ ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ๋‹ค์ค‘ ์Šค๋ ˆ๋“œ ๋ชจ๋ธ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ์—ฌ๋Ÿฌ ์“ฐ๋ ˆ๋“œ์—์„œ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋Ÿฌํ•œ ์“ฐ๋ ˆ๋“œ๋Š” ์ด๋ฒคํŠธ ๋ฃจํ”„์—์„œ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ์ž‘์—…์„ ์ œ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

val loop = LoopResources.create("event-loop", 1, 4, true)

val server = TcpServer.create()
    .runOn(loop)
    .bindNow()
    .onDispose()
    .block()

Client

๊ตฌํ˜„์ฒด๋งŒ TcpClient๋กœ ๋ฐ”๋€Œ๊ณ  Server๋ž‘ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

val connetor =  TcpClient.create()
        .port(9988)
        .host("localhost")
        .connectNow()

Last updated