RingLibuv の用法 — プログラミング言語 Ring 1.14 取扱説明書

Skip to content

# RingLibuv の用法

RingLibuv の用法です。

注釈

RingLibuv の用法は ring/extensions/ringlibuv フォルダを参照してください。

ライブラリのウェブサイトからの情報: http://libuv.org/

Libuv は非同期 I/O に主眼を置いたマルチプラットフォーム対応ライブラリです。

特筆すべき機能

- epoll, kqueue, IOCP, イベントポートによる完全機能のイベントループへの対応。

- 非同期 TCP および UDP ソケット

- 非同期 DNS 解決

- 非同期ファイル、およびファイルシステム操作

- ファイルシステムのイベント

- TTY 制御による ANSI エスケープコード

- Unix ドメインソケットまたは名前つきパイプ (Windows) による IPC ソケット共有

- 子プロセス

- スレッドプール

- シグナル処理

- 高分解能クロック

- スレッド処理と同期基本命令

## RingLibuv によるはじめてのアプリケーション

用例:

    load "libuv.ring"

    func main

            myloop = new_uv_loop_t()
            uv_loop_init(myloop)
            ? "Now quitting"
            uv_run(myloop, UV_RUN_DEFAULT)
            uv_loop_close(myloop)
            destroy_uv_loop_t(myloop)

実行結果:

    Now quitting

## イベントループ

用例:

    load "libuv.ring"

    counter = 0
    idler = NULL

    func main
            idler = new_uv_idle_t()
            uv_idle_init(uv_default_loop(), idler)
            uv_idle_start(idler, "wait()")
            ? "Idling..."
            uv_run(uv_default_loop(), UV_RUN_DEFAULT);
            uv_loop_close(uv_default_loop());
            destroy_uv_idle_t(idler)

    func wait
            counter++
            if counter >= 100000
                    uv_idle_stop(idler)
            ok

実行結果:

    Idling...

## サーバーの用例

用例:

    load "libuv.ring"

    ? "Testing RingLibuv - Server Side"

    DEFAULT_PORT    = 13370
    DEFAULT_BACKLOG = 1024

    addr    = new_sockaddr_in()
    server  = NULL
    client  = NULL
    myloop  = NULL

    func main
            myloop = uv_default_loop()
            server = new_uv_tcp_t()
            uv_tcp_init(myloop, server)
            uv_ip4_addr("127.0.0.1", DEFAULT_PORT, addr)
            uv_tcp_bind(server, addr, 0)
            r = uv_listen(server, DEFAULT_BACKLOG, "newconnection()")
            if r
                    ? "Listen error " + uv_strerror(r)
                    return 1
            ok
            uv_run(myloop, UV_RUN_DEFAULT)
            destroy_uv_tcp_t(server)
            destroy_uv_sockaddr_in(addr)

    func newconnection
            ? "New Connection"
            aPara   = uv_Eventpara(server,:connect)
            nStatus = aPara[2]
            if nStatus < 0
                    ? "New connection error : " + nStatus
                    return
            ok
            client = new_uv_tcp_t()
            uv_tcp_init(myloop, client)
            if uv_accept(server, client) = 0
                            uv_read_start(client, uv_myalloccallback(), "echo_read()")
            ok

    func echo_read
            aPara = uv_Eventpara(client,:read)
            nRead = aPara[2]
            buf   = aPara[3]
            if nRead > 0
                    req = new_uv_write_t()
                            wrbuf = uv_buf_init(get_uv_buf_t_base(buf), nread)
                    uv_write(req, client, wrbuf, 1, "echo_write()")
                    ? uv_buf2str(wrbuf)
                    message = "message from the server to the client"
                    buf = new_uv_buf_t()
                    set_uv_buf_t_len(buf,len(message))
                    set_uv_buf_t_base(buf,varptr("message",:char))
                    uv_write(req, client, buf, 1, "echo_write()")
            ok

    func echo_write
            aPara = uv_Eventpara(client,:read)
            req   = aPara[1]

実行結果:

クライアントを実行すると、“New Connection”メッセージが表示されます。

そして “hello from the client” メッセージが表示されます。

    Testing RingLibuv - Server Side
    New Connection
    hello from the client

## クライアントの用例

用例:

    load "libuv.ring"

    ? "Testing RingLibuv - Client Side"

    DEFAULT_PORT    = 13370
    DEFAULT_BACKLOG = 1024

    addr    = new_sockaddr_in()
    connect = NULL
    buffer  = null
    socket  = null

    func main
            myloop  = uv_default_loop()
            Socket  = new_uv_tcp_t()
            connect = new_uv_connect_t()
            uv_tcp_init(myloop, Socket)
            uv_ip4_addr("127.0.0.1", DEFAULT_PORT, addr)
            uv_tcp_connect(connect,Socket, addr, "connect()")
            uv_run(myloop, UV_RUN_DEFAULT)
            destroy_uv_tcp_t(socket)
            destroy_uv_connect_t(connect)

    func connect
            ? "Client: Start Connection"
            aPara   = uv_Eventpara(connect,:connect)
            req     = aPara[1]
            nStatus = aPara[2]
            if nStatus = -1
                    ? "Error : on_write_end "
                    return
            ok
            buf = new_uv_buf_t()
            message = "hello from the client"
            set_uv_buf_t_len(buf,len(message))
            set_uv_buf_t_base(buf,varptr("message",:char))
            tcp       = get_uv_connect_t_handle(req)
            write_req = new_uv_write_t()
            buf_count = 1
            uv_write(write_req, tcp, buf, buf_count, "on_write_end()")

    func on_write_end
                    uv_read_start(socket, uv_myalloccallback(), "echo_read()")

    func echo_read
            aPara = uv_Eventpara(socket,:read)
            nRead = aPara[2]
            buf   = aPara[3]
            if nRead > 0
                            wrbuf = uv_buf_init(get_uv_buf_t_base(buf), nread);
                    ? uv_buf2str(wrbuf)
            ok

実行結果:

サーバーの後にクライアントを実行します。

    Testing RingLibuv - Client Side
    Client: Start Connection
    hello from the client
    message from the server to the client

## クラスによるサーバーの用例

用例:

    load "libuv.ring"
    load "objectslib.ring"

    ? "Testing RingLibuv - Server Side - Using Classes"

    open_object(:MyServer)

    class MyServer from ObjectControllerParent

            DEFAULT_PORT    = 13370
            DEFAULT_BACKLOG = 1024

            addr    = new_sockaddr_in()
            server  = NULL
            client  = NULL
            myloop  = NULL

            func start
                    myloop = uv_default_loop()
                    server = new_uv_tcp_t()
                    uv_tcp_init(myloop, server)
                    uv_ip4_addr("127.0.0.1", DEFAULT_PORT, addr)
                    uv_tcp_bind(server, addr, 0)
                    r = uv_listen(server, DEFAULT_BACKLOG, Method(:newconnection) )
                    if r
                            ? "Listen error " + uv_strerror(r)
                            return 1
                    ok
                    uv_run(myloop, UV_RUN_DEFAULT)
                    destroy_uv_tcp_t(server)
                    destroy_uv_sockaddr_in(addr)

            func newconnection
                    ? "New Connection"
                    aPara   = uv_Eventpara(server,:connect)
                    nStatus = aPara[2]
                    if nStatus < 0
                            ? "New connection error : " + nStatus
                            return
                    ok
                    client = new_uv_tcp_t()
                    uv_tcp_init(myloop, client)
                    if uv_accept(server, client) = 0
                                    uv_read_start(client, uv_myalloccallback(),
                                                            Method(:echo_read))
                    ok

            func echo_read
                    aPara = uv_Eventpara(client,:read)
                    nRead = aPara[2]
                    buf   = aPara[3]
                    if nRead > 0
                            req = new_uv_write_t()
                                    wrbuf = uv_buf_init(get_uv_buf_t_base(buf), nread)
                            uv_write(req, client, wrbuf, 1, Method(:echo_write))
                            ? uv_buf2str(wrbuf)
                            message = "message from the server to the client"
                            buf = new_uv_buf_t()
                            set_uv_buf_t_len(buf,len(message))
                            set_uv_buf_t_base(buf,varptr("message",:char))
                            uv_write(req, client, buf, 1, Method(:echo_write))
                    ok

            func echo_write
                    aPara = uv_Eventpara(client,:read)
                    req   = aPara[1]

実行結果:

クライアントを実行すると、“New Connection”メッセージが表示されます。

そして“hello from the client”メッセージが表示されます。

    Testing RingLibuv - Server Side - Using Classes
    New Connection
    hello from the client

## クラスによるクライアントの用例

用例:

    load "libuv.ring"
    load "objectslib.ring"

    ? "Testing RingLibuv - Client Side - Using Classes"

    open_object(:MyClient)

    Class MyClient from ObjectControllerParent

            DEFAULT_PORT    = 13370
            DEFAULT_BACKLOG = 1024

            addr    = new_sockaddr_in()
            connect = NULL
            buffer  = null
            socket  = null

            func start
                    myloop  = uv_default_loop()
                    Socket  = new_uv_tcp_t()
                    connect = new_uv_connect_t()
                    uv_tcp_init(myloop, Socket)
                    uv_ip4_addr("127.0.0.1", DEFAULT_PORT, addr)
                    uv_tcp_connect(connect,Socket, addr, Method(:connect))
                    uv_run(myloop, UV_RUN_DEFAULT)
                    destroy_uv_tcp_t(socket)
                    destroy_uv_connect_t(connect)

            func connect
                    ? "Client: Start Connection"
                    aPara   = uv_Eventpara(connect,:connect)
                    req     = aPara[1]
                    nStatus = aPara[2]
                    if nStatus = -1
                            ? "Error : on_write_end "
                            return
                    ok
                    buf = new_uv_buf_t()
                    message = "hello from the client"
                    set_uv_buf_t_len(buf,len(message))
                    set_uv_buf_t_base(buf,varptr("message",:char))
                    tcp       = get_uv_connect_t_handle(req)
                    write_req = new_uv_write_t()
                    buf_count = 1
                    uv_write(write_req, tcp, buf, buf_count, Method(:on_write_end))

            func on_write_end
                            uv_read_start(socket, uv_myalloccallback(), Method(:echo_read))

            func echo_read
                    aPara = uv_Eventpara(socket,:read)
                    nRead = aPara[2]
                    buf   = aPara[3]
                    if nRead > 0
                                    wrbuf = uv_buf_init(get_uv_buf_t_base(buf), nread);
                            ? uv_buf2str(wrbuf)
                    ok

実行結果:

サーバーの後にクライアントを実行します。

    Testing RingLibuv - Client Side - Using Classes
    Client: Start Connection
    hello from the client
    message from the server to the client

## スレッドの用例

用例:

    load "libuv.ring"

    ? "Testing RingLibuv - Threads"

    func main
            one_id = new_uv_thread_t()
            two_id = new_uv_thread_t()
            uv_thread_create(one_id, "one()")
            uv_thread_create(two_id, "two()")
            uv_thread_join(one_id)
            uv_thread_join(two_id)
            destroy_uv_thread_t(one_id)
            destroy_uv_thread_t(two_id)

    func one
            ? "Message from the First Thread!"

    func two
            ? "Message from the Second Thread!"

実行結果:

    Testing RingLibuv - Threads
    Message from the First Thread!
    Message from the Second Thread!

## スレッドの用例 - クラスの使用

用例:

    load "libuv.ring"
    load "objectslib.ring"

    ? "Testing RingLibuv - Threads - Using Classes"

    open_object(:MyThreads)

    class MyThreads from ObjectControllerParent

            func Start
                    one_id = new_uv_thread_t()
                    two_id = new_uv_thread_t()
                    uv_thread_create(one_id, Method(:One))
                    uv_thread_create(two_id, Method(:Two))
                    uv_thread_join(one_id)
                    uv_thread_join(two_id)
                    destroy_uv_thread_t(one_id)
                    destroy_uv_thread_t(two_id)

            func one
                    ? "Message from the First Thread!"

            func Two
                    ? "Message from the Second Thread!"

実行結果:

    Testing RingLibuv - Threads - Using Classes
    Message from the First Thread!
    Message from the Second Thread!