Using RingLibuv
In this chapter we will learn about using RingLibuv
Note
To use RingLibuv, Check ring/extensions/ringlibuv folder.
Information from the library website: http://libuv.org/
Libuv is a multi-platform support library with a focus on asynchronous I/O.
Feature highlights
- Full-featured event loop backed by epoll, kqueue, IOCP, event ports.
- Asynchronous TCP and UDP sockets
- Asynchronous DNS resolution
- Asynchronous file and file system operations
- File system events
- ANSI escape code controlled TTY
- IPC with socket sharing, using Unix domain sockets or named pipes (Windows)
- Child processes
- Thread pool
- Signal handling
- High resolution clock
- Threading and synchronization primitives
First Application using RingLibuv
Example:
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)
Output:
Now quitting
The Events Loop
Example:
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
Output:
Idling...
Server Example
Example:
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]
Output:
When we run the client, We will see the message “New Connection”
Then the message “hello from the client”
Testing RingLibuv - Server Side
New Connection
hello from the client
Client Example
Example:
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
Output:
We will run the client after the server
Testing RingLibuv - Client Side
Client: Start Connection
hello from the client
message from the server to the client
Server Example Using Classes
Example:
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]
Output:
When we run the client, We will see the message “New Connection”
Then the message “hello from the client”
Testing RingLibuv - Server Side - Using Classes
New Connection
hello from the client
Client Example Using Classes
Example:
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
Output:
We will run the client after the server
Testing RingLibuv - Client Side - Using Classes
Client: Start Connection
hello from the client
message from the server to the client
Threads Example
Example:
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!"
Output:
Testing RingLibuv - Threads
Message from the First Thread!
Message from the Second Thread!
Threads Example - Using Classes
Example:
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!"
Output:
Testing RingLibuv - Threads - Using Classes
Message from the First Thread!
Message from the Second Thread!