sockets 1.6 - tsafin/tarantool GitHub Wiki
box.errno
A list of error codes from (7) errno.h
exported to Lua.
Methods:
box.errno()
- last errnobox.errno.E*
- error codes from(7) errno.h
(for example,box.errno.EBUSY
)box.errno.strerror(code)
- returns string error description based on error code
Domain Name Resolution
box.socket.getaddrinfo(host, port[, timeout][, hints ])
Returns an array with hosts, e.g.:
{
{ host = '127.0.0.1', port = 8080, family = 'AF_INET', type = 'SOCK_STREAM', protocol = 'tcp' },
{ host = '::1', port = 8080, family = 'AF_INET6', type = 'SOCK_STREAM', protocol = 'tcp' },
...
}
Optional hints
argument is a Lua table with one of several of the hints below:
family
- protocol family (a string such as 'AF_INET', 'AF_UNIX', etc)
type
- socket type (string, 'SOCK_STREAM', 'SOCK_DGRAM', etc)
protocol
- protocol name (string, 'tcp', 'ip', etc)
flags
- a table with flags (strings in AI_* family)
Any value of the returned array can be used to create a socket.
In case of error, returns n nil
. Use box.errno()
to find out
more about the occurred error.
Creating a socket
s = box.socket(domain, type, protocol)
Domain, type, protocol - string constants with names identical to one in
man 2 socket and to the contents of /etc/protocols
Returns a socket object, or nil in case of error.
In case of error, an error code and a text description of the error are available with:
socket:errno()
and socket:error()
Example:
local s = socket('AF_INET', 'SOCK_STREAM', 'tcp')
s:errno()
, s:error()
Error code and error message of the last error occurred on this socket.
s:sysconnect(host, port)
A low level binding to man 2 connect
, which tries to connect
to the given address .
host
, port
- must be an IPv4, IPv6 address or a UNIX path.
local s = box.socket('PF_INET', 'SOCK_STREAM', 'tcp')
if not s:sysconnect('127.0.0.1', 80) then
error("Can't connect to server '127.0.0.1:80': " .. s:error())
end
s:write("HEAD / HTTP/1.1\r\nHost: mail.ru\r\nConnection: close\r\n\r\n")
return s:readline({ "\r\n\r\n", "\n\n" })
s:sysread(count)
A low level read. Issues man 2 read
under the hood. Returns
a Lua string (possibly empty) with read data.
In case of error, returns nil
. Can block the calling process
in case the socket is blocking.
local data = s:sysread(4096)
if data == nil then
error(s:error())
end
buf = buf .. data
s:syswrite(string)
A low level write. Calls man 2 write
under the hood. Returns the number
of bytes written or nil
in case of error.
Can block the calling process if the socket is blocking.
local sent = s:syswrite('Hello, world')
if sent == nil then
error(s:error())
end
s:nonblock([flag])
Get, set or clear the non-blocking socket flag. Returns the current value of the flag.
s:close()
Close the socket. Returns true
in case of success or false
in
case of error.
s:shutdown(how)
Shut down the reading or writing end of the socket, or both.
See man 2 shutdown
. Returns true
in case of success and false
in case of error.
how
can be one of the following:
R
orREAD
or0
- close the reading endW
orWRITE
or1
- close the wtiting endRW
orREAD_WRITE
or2
- close both the reading and the writing end.
s:sysbind(host, port)
Bind a socket to a host/port pair. The host and port must not
require a domain name resolution, same as in :sysconnect
.
Returns true
on success and false
on error.
s:listen(backlog)
Begins listening on a socket. See also man 2 listen
.
Returns true
on success and false
on error.
s:accept()
Accepts an incoming connection. Returns a new socket or nil
in
case of error. Can block the calling process unless the socket
is marked as non-blocking.
Note that the new socket inherits the blocking mode
from the acceptor socket on some operating system, and
does not inherits the mode on others, so it is a good
practice to set the mode explicitly on the accepted socket.
s:setsockopt(level, name, value)
and s:getsockopt(level, name)
Set or clear socket flags (see man setsockopt
and man getsockopt
). Supports the following flags:
SO_ACCEPTCONN
,
SO_BINDTODEVICE
, SO_BROADCAST
, SO_BSDCOMPAT
, SO_DEBUG
,
SO_DOMAIN
, SO_ERROR
, SO_DONTROUTE
, SO_KEEPALIVE
,
SO_MARK
, SO_OOBINLINE
, SO_PASSCRED
, SO_PEERCRED
,
SO_PRIORITY
, SO_PROTOCOL
, SO_RCVBUF
, SO_RCVBUFFORCE
,
SO_RCVLOWAT
, SO_SNDLOWAT
, SO_RCVTIMEO
, SO_SNDTIMEO
,
SO_REUSEADDR
, SO_SNDBUF
, SO_SNDBUFFORCE
, SO_TIMESTAMP
,
SO_TYPE
.
Setting or clearing SO_LINGER
is done with so:linger(active, timeout)
s:readable([timeout])
Block the calling fiber until the socket becomes readable or
the timeout expires.
Returns true
if/when the socket has data available for reading, and
false
in case of error or timeout.
s:writable([timeout])
Block the calling fiber until the socket becomes writable or
the timeout expires.
Returns true
if/when the socket is available for reading, and
false
in case of error or timeout.
s:wait([timeout])
Block the calling fiber until the socket becomes readable or writable or
the timeout expires.
Returns string R
, W
, RW
, describing the state of the socket,
or nil
in case of timeout.
s:read([len[, timeout]])
A wrapper around s:sysread()
.
Reads data from the socket until one of the following
conditions is met:
- the number of bytes read is at least
len
eof
is read from the socket (sysread
returns 0 bytes)- timeout is reached
- a read error occurred
Returns a string with data in cases of success or nil
in case of error.
Notes:
- the data is read into an internal buffer,
s.rbuf
- if there is data already in
s.rbuf
this data is taken into account in a subsequent call tos:read()
ands:readline()
(but not ins:sysread()
) s:sysread()
bypassess.rbuf
s:readline([len], [eols], [timeout])
A wrapper around s:sysread()
.
Read data from the socket until one of the following conditions is met:
- A string ending with one of the markers passed in
eols
table is read eof
is read (sysread()
returns 0 bytes)- timeout is reached
- length limit (passed in
len
) is reached - error occurred
Returns a string with data in case of success and `nil in case of error.
Uses s.rbuf
along with s:read()
.
s:write(str[, timeout])
A wrapper around s:syswrite()
.
Write str to the socket, untl one of the following
events occurs:
- str is fully written
- timeout is reached.
- an error occurred.
Returns true
on success and false
on error.
s:recv(size[, flags])
and s:send(str[, flags])
Receive or send a datagramm. See man 3 recv
и man 3 send
.
s:send()
returns true
on success and false
on error.
s:recv()
returns a string with a datagram on success and nil
in case of error.
Examples
Connect to a TCP server
function tcp_connect(host, port)
local ainfo =
box.socket.getaddrinfo(host, port, nil, { protocol = 'tcp' })
if ainfo == nil then
error( box.errno.strerror(box.errno()) )
end
for i, a in pairs(ainfo) do
local s = box.socket(a.family, a.type, a.protocol)
if s == nil then
error( box.errno.strerror(box.errno()) )
end
s:nonblock(true)
if s:sysconnect(a.host, a.port) then
return s
end
end
error("Can't connect to " .. host .. ":" .. port)
end
A simple HTTP client
function http_request(host, port, request)
local s = tcp_connect(host, port)
s:write(request)
local header = s:readline(4096, { "\r\n\r\n", "\n\n" })
header = parse_header(header)
local body = s:read(header['content-length'])
return body, header
end
A simple Echo-server
local ms = box.socket('PF_INET', 'SOCK_STREAM', 'tcp')
ms:nonblock(true)
ms:bind('127.0.0.1', 8080)
ms:listen(128)
while ms:readable() do
local client = ms:accept()
client:nonblock(true)
box.fiber.wrap(
function(client)
local request = client:readline(512, { "\n" })
client:shutdown('READ')
client:write(request)
client:close()
end,
client)
end
ms:close()
A simple Echo-server (working)
local socket = require('socket')
local fiber = require('fiber')
local ms = socket('PF_INET', 'SOCK_STREAM', 'tcp')
ms:setsockopt('SOL_SOCKET', 'SO_REUSEADDR', true)
ms:nonblock(true)
ms:bind('127.0.0.1', 8080)
ms:listen(128)
while ms:readable() do
local client = ms:accept()
client:nonblock(true)
fiber.create(
function(client)
client:readable()
local request = client:recv()
client:shutdown('READ')
client:write(request)
client:close()
end,
client)
end
ms:close()
A high level TCP connect
socket.tcp_connect()
local socket = box.socket.tcp_connect(host, port, timeout)
This functions resolves the host and port, and establishes
a connection.
If host
contains string unix/
, then port
must contain a path to a
UNIX-socket.