NIO入门

本文开发语言基于Swift 代码参考EchoServer

目录

环境

MacOS安装Xcode即可 所以以下环境搭建基于Ubuntu1604

sudo apt install -y clang libicu-dev git
git clone https://github.com/kylef/swiftenv.git ~/.swiftenv

echo 'export SWIFTENV_ROOT="$HOME/.swiftenv"' >> ~/.zshrc

echo 'export PATH="$SWIFTENV_ROOT/bin:$PATH"' >> ~/.zshrc

echo 'eval "$(swiftenv init -)"' >> ~/.zshrc

source ~/.zshrc
swiftenv install 4.0.3

swift --version

关于swiftenv 更多参考swiftenv

开始

mkdir EchoServer

# cd EchoServer
swift package init --type executable
swift build

.build/debug/EchoServer
Hello, world!

NIO

vim Package.swift
// swift-tools-version:4.0
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "EchoServer",
    dependencies: [
        // Dependencies declare other packages that this package depends on.
        // .package(url: /* package url */, from: "1.0.0"),
        .package(url: "https://github.com/apple/swift-nio.git", from: "1.1.0"),
    ],
    targets: [
        // Targets are the basic building blocks of a package. A target can define a module or a test suite.
        // Targets can depend on other targets in this package, and on products in packages which this package depends on.
        .target(
            name: "EchoServer",
            dependencies: ["NIO"]),
    ]
)
swift package resolve
vim Sources/EchoServer/main.swift
import NIO

// EchoHandler
private final class EchoHandler: ChannelInboundHandler {
    public typealias InboundIn = ByteBuffer
    public typealias OutboundOut = ByteBuffer

    private var count: Int = 0

    public func channelRegistered(ctx: ChannelHandlerContext) {
        print("channel registered:", ctx.remoteAddress ?? "unknown")
    }

    public func channelUnregistered(ctx: ChannelHandlerContext) {
        print("channel unregistered")
    }

    public func channelRead(ctx: ChannelHandlerContext, data: NIOAny) {
        let buffer = self.unwrapInboundIn(data)
        print("read:", buffer.getString(at: 0, length: buffer.readableBytes)!)
        ctx.write(data, promise: nil)
    }

    public func channelReadComplete(ctx: ChannelHandlerContext) {
        print("read complete")
        ctx.flush()
    }

    public func errorCaught(ctx: ChannelHandlerContext, error: Error) {
        print("error: ", error)
        ctx.close(promise: nil)
    }
}

// Bootstrap
let group = MultiThreadedEventLoopGroup(numThreads: System.coreCount)
let bootstrap = ServerBootstrap(group: group)
        .serverChannelOption(ChannelOptions.backlog, value: 256)
        .serverChannelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
        .childChannelInitializer { channel in
            channel.pipeline.add(handler: BackPressureHandler()).then { v in
                channel.pipeline.add(handler: EchoHandler())
            }
        }
        .childChannelOption(ChannelOptions.socket(IPPROTO_TCP, TCP_NODELAY), value: 1)
        .childChannelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
        .childChannelOption(ChannelOptions.maxMessagesPerRead, value: 16)
        .childChannelOption(ChannelOptions.recvAllocator, value: AdaptiveRecvByteBufferAllocator())
defer {
    try! group.syncShutdownGracefully()
}

let channel = try bootstrap.bind(host: "::1", port: 9999).wait()
print("Server started and listening on \(channel.localAddress!)")
try channel.closeFuture.wait()
print("Server terminated")

测试

  • Server
swift build && .build/debug/EchoServer
Compile Swift Module 'EchoServer' (1 sources)
Server started and listening on [IPv6]::1:9999
  • Client
telnet localhost 9999

MacOS安装telnet方法: brew install telnet

Trying ::1...
Connected to localhost.
Escape character is '^]'.
  • Close
^]
telnet> close

概念

mkdir Node

# cd Node
echo "file content" >> ./file

Blocking I/O

vim bio.js
console.log('start')
const data = require('fs').readFileSync('./file');
console.log('read:', data.toString());
console.log('end');
node bio.js
start
read: file content

end

Non-Blocking I/O

vim nio.js
console.log('start')
require('fs').readFile('./file', (err, data) => {
    if (err) throw err;
    console.log(data.toString());
});
console.log('end');
node nio.js
start
end
read: file content

参考

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 关于多路复用 很多人用过InputStream和OutputStream接口,用来操作文件、Socket等等 IO...
    Gemini阅读 2,548评论 0 0
  • 这两天了解了一下关于NIO方面的知识,网上关于这一块的介绍只是介绍了一下基本用法,没有系统的解释NIO与阻塞、非阻...
    Ruheng阅读 11,937评论 5 48
  • NIO(Non-blocking I/O,在Java领域,也称为New I/O),是一种同步非阻塞的I/O模型,也...
    闪电是只猫阅读 8,344评论 0 7
  • 此时的你不够努力,导致现在的你无能为力!
    在下石麒麟阅读 1,183评论 0 0
  • 时间7:00-7:30 书页:15-34 书名:《心理咨询师》 书摘: 感想:这部分知识是基础,我没什么联想和太多...
    不要多愁善感阅读 1,280评论 0 1