The example used by Bert Belder at LXJS 2012 to introduce the libuv basics.
- See also
- Video at youtube.com: "LXJS 2012 - Bert Belder - libuv".
The original code is slightly modified to work with recent libuv versions > 0.10.
example/lxjs2012-demo-uv.c
12 void after_getaddrinfo(uv_getaddrinfo_t*,
int,
struct addrinfo*);
13 void after_connect(uv_connect_t*,
int);
14 void after_write(uv_write_t*,
int);
15 void on_alloc(uv_handle_t*,
size_t, uv_buf_t*);
16 void on_read(uv_stream_t*, ssize_t,
const uv_buf_t*);
17 void on_close(uv_handle_t*);
20 int main(
int _argc,
char *_argv[])
22 uv_getaddrinfo_t* gai_req = (uv_getaddrinfo_t*)
malloc(
sizeof(uv_getaddrinfo_t));
33 uv_run(uv_default_loop(), UV_RUN_DEFAULT);
40 void after_getaddrinfo(uv_getaddrinfo_t *_gai_req,
int _status,
struct addrinfo *_ai)
43 uv_connect_t *connect_req;
45 if (_status < 0)
abort();
47 tcp_handle = (uv_tcp_t*)
malloc(
sizeof(uv_tcp_t));
48 uv_tcp_init(uv_default_loop(), tcp_handle);
50 connect_req = (uv_connect_t*)
malloc(
sizeof(uv_connect_t));
63 void after_connect(uv_connect_t *_connect_req,
int _status)
65 uv_write_t *write_req;
68 if (_status < 0)
abort();
70 write_req = (uv_write_t*)
malloc(
sizeof(uv_write_t));
72 buf.base = (
char*)
"GET / HTTP/1.0\r\n" 73 "Host: www.nyan.cat\r\n" 75 buf.len =
strlen(buf.base);
95 void after_write(uv_write_t *_write_req,
int _status)
97 if (_status < 0)
abort();
102 void on_alloc(uv_handle_t *_handle,
size_t _suggested_size, uv_buf_t* _buf)
104 _buf->base = (
char*)
malloc(_suggested_size);
105 _buf->len = _suggested_size;
109 void on_read(uv_stream_t *_tcp_handle, ssize_t _nread,
const uv_buf_t *_buf)
113 if (_nread == UV_EOF)
116 (uv_handle_t*) _tcp_handle,
128 fwrite(_buf->base, 1, _nread, stdout);
135 void on_close(uv_handle_t *_handle)
Here is the very same program being rewritten using uvcc. One can find that the code has become more compact and has far less "translation noise".
example/lxjs2012-demo-uvcc.cpp
11 #define PRINT_UV_ERR(code, printf_args...) do {\ 13 fprintf(stderr, "" printf_args);\ 14 fprintf(stderr, ": %s (%i): %s\n", ::uv_err_name(code), (int)(code), ::uv_strerror(code));\ 22 int main(
int _argc,
char *_argv[])
31 PRINT_UV_ERR(_gai_req.uv_status(),
"getaddrinfo");
41 connect_req.on_request() = connect_cb;
43 connect_req.
run(tcp_handle, *_gai_req.addrinfo()->ai_addr);
58 PRINT_UV_ERR(_connect_req.
uv_status(),
"connect");
67 buf.
base() =
const_cast< char*
>(
69 "Host: www.nyan.cat\r\n" 77 wr.run(tcp_handle, buf);
88 if (_nread != UV_EOF) PRINT_UV_ERR(_nread,
"read");
94 fwrite(_buf.base(), 1, _nread, stdout);
Stream connect request type.
Getaddrinfo request type.
decltype(uv_t::len) & len(const std::size_t _i=0) const noexcept
The .len field of the _i-th buffer structure.
int read_stop() const
Stop reading data from the I/O endpoint.
The base class for the libuv handles.
int run(tcp &_tcp, const _T_ &_sockaddr)
Run the request for uv::tcp stream.
static loop & Default() noexcept
Returns the initialized loop that can be used as a global default loop throughout the program...
int run(uv::loop &_loop, const char *_hostname, const char *_service, const ::addrinfo &_hints)
Run the request.
int run(::uv_run_mode _mode)
Go into a loop and process events and their callbacks with the current thread.
int uv_status() const noexcept
The status value returned by the last executed libuv API function on this request.
Stream write request type.
The base class for handles representing I/O endpoints: a file, TCP/UDP socket, pipe, TTY.
decltype(uv_t::base) & base(const std::size_t _i=0) const noexcept
The .base field of the _i-th buffer structure.
stream handle() const noexcept
The stream which this connect request has been running on.
Encapsulates uv_buf_t data type and provides uv_buf_t[] functionality.
int read_start(std::size_t _size=0, int64_t _offset=-1) const
Start reading incoming data from the I/O endpoint.
- See also
- There are another helpful introductory talks on libuv that can be found at youtube.com:
"Introduction to libuv – Thorsten Lorenz",
"using libuv and http parser to build a webserver".
Here are the examples of the elementary TCP client and server programs written with uvcc. Each program sends a greeting to the remote peer, closes its write side of the TCP connection and keeps reading from the remote peer until it closes the connection.
example/hello-tcp-server.cpp
6 #define PRINT_UV_ERR(code, printf_args...) do {\ 8 fprintf(stderr, "" printf_args);\ 9 fprintf(stderr, ": %s (%i): %s\n", ::uv_err_name(code), (int)(code), ::uv_strerror(code));\ 14 int main(
int _argc,
char *_argv[])
17 sockaddr_storage listen_addr;
19 const char *ip = _argc > 1 ? _argv[1] :
"127.0.0.1";
20 const char *port = _argc > 2 ? _argv[2] :
"54321";
22 int status =
uv::init(listen_addr, ip, port);
25 PRINT_UV_ERR(status,
"ip address");
36 server.bind(listen_addr);
39 PRINT_UV_ERR(server.uv_status(),
"tcp socket bind");
40 return server.uv_status();
45 greeting.
base() =
const_cast< char*
>(
"server: Hello from uvcc!\n");
54 PRINT_UV_ERR(_server.
uv_status(),
"incoming connection");
58 _server.attached(
false);
62 if (!client) PRINT_UV_ERR(client.uv_status(),
"accept");
67 wr.run(client, greeting);
68 if (!wr) PRINT_UV_ERR(wr.uv_status(),
"write initiation");
83 if (_nread != UV_EOF) PRINT_UV_ERR(_nread,
"read");
89 fwrite(_buf.base(), 1, _nread, stdout);
94 if (!client) PRINT_UV_ERR(client.uv_status(),
"read initiation");
99 PRINT_UV_ERR(server.uv_status(),
"listen");
100 return server.uv_status();
int run(stream &_stream)
Run the request.
decltype(uv_t::len) & len(const std::size_t _i=0) const noexcept
The .len field of the _i-th buffer structure.
Stream shutdown request type.
int uv_status() const noexcept
The status value returned by the last executed libuv API function on this handle. ...
int read_stop() const
Stop reading data from the I/O endpoint.
The base class for the libuv handles.
static loop & Default() noexcept
Returns the initialized loop that can be used as a global default loop throughout the program...
int run(::uv_run_mode _mode)
Go into a loop and process events and their callbacks with the current thread.
int uv_status() const noexcept
The status value returned by the last executed libuv API function on this request.
Stream write request type.
The base class for handles representing I/O endpoints: a file, TCP/UDP socket, pipe, TTY.
int init(::sockaddr_in &_sin)
Initialize a sockaddr_in structure.
decltype(uv_t::base) & base(const std::size_t _i=0) const noexcept
The .base field of the _i-th buffer structure.
Encapsulates uv_buf_t data type and provides uv_buf_t[] functionality.
stream accept() const
Accept incoming connections.
example/hello-tcp-client.cpp
6 #define PRINT_UV_ERR(code, printf_args...) do {\ 8 fprintf(stderr, "" printf_args);\ 9 fprintf(stderr, ": %s (%i): %s\n", ::uv_err_name(code), (int)(code), ::uv_strerror(code));\ 14 int main(
int _argc,
char *_argv[])
17 sockaddr_storage server_addr;
19 const char *ip = _argc > 1 ? _argv[1] :
"127.0.0.1";
20 const char *port = _argc > 2 ? _argv[2] :
"54321";
22 int status =
uv::init(server_addr, ip, port);
25 PRINT_UV_ERR(status,
"ip address");
33 PRINT_UV_ERR(peer.uv_status(),
"tcp socket");
34 return peer.uv_status();
39 greeting.
base() =
const_cast< char*
>(
"client: Hello from uvcc!\n");
48 PRINT_UV_ERR(_conn.uv_status(),
"connect");
52 auto peer =
static_cast< uv::tcp&&
>(_conn.handle());
57 wr.
run(peer, greeting);
58 if (!wr) PRINT_UV_ERR(wr.
uv_status(),
"write initiation");
73 if (_nread != UV_EOF) PRINT_UV_ERR(_nread,
"read");
79 fwrite(_buf.base(), 1, _nread, stdout);
84 if (!peer) PRINT_UV_ERR(peer.uv_status(),
"read initiation");
88 conn.run(peer, server_addr);
91 PRINT_UV_ERR(conn.uv_status(),
"connect initiation");
92 return conn.uv_status();
Stream connect request type.
int run(stream &_stream, const buffer &_buf)
Run the request.
int run(stream &_stream)
Run the request.
decltype(uv_t::len) & len(const std::size_t _i=0) const noexcept
The .len field of the _i-th buffer structure.
Stream shutdown request type.
int read_stop() const
Stop reading data from the I/O endpoint.
The base class for the libuv handles.
static loop & Default() noexcept
Returns the initialized loop that can be used as a global default loop throughout the program...
int run(::uv_run_mode _mode)
Go into a loop and process events and their callbacks with the current thread.
int uv_status() const noexcept
The status value returned by the last executed libuv API function on this request.
Stream write request type.
The base class for handles representing I/O endpoints: a file, TCP/UDP socket, pipe, TTY.
int init(::sockaddr_in &_sin)
Initialize a sockaddr_in structure.
decltype(uv_t::base) & base(const std::size_t _i=0) const noexcept
The .base field of the _i-th buffer structure.
Encapsulates uv_buf_t data type and provides uv_buf_t[] functionality.