Модуль socket¶
The socket
module allows exchanging data via BSD sockets with a local or
remote host in connection-oriented (TCP) or datagram-oriented (UDP) mode.
Semantics of the calls in the socket
API closely follow semantics of the
corresponding POSIX calls. Function names and signatures are mostly compatible
with luasocket.
The functions for setting up and connecting are socket
, sysconnect
,
tcp_connect
. The functions for sending data are send
, sendto
,
write
, syswrite
. The functions for receiving data are recv
,
recvfrom
, read
. The functions for waiting before sending/receiving
data are wait
, readable
, writable
. The functions for setting
flags are nonblock
, setsockopt
. The functions for stopping and
disconnecting are shutdown
, close
. The functions for error checking
are errno
, error
.
Socket functions
Purposes | Names |
---|---|
setup | socket() |
«» | socket.tcp_connect() |
«» | socket.tcp_server() |
«» | socket_object:sysconnect() |
«» | socket_object:send() |
sending | socket_object:sendto() |
«» | socket_object:write() |
«» | socket_object:syswrite() |
receiving | socket_object:recv() |
«» | socket_object:recvfrom() |
«» | socket_object:read() |
flag setting | socket_object:nonblock() |
«» | socket_object:setsockopt() |
«» | socket_object:linger() |
client/server | socket_object:listen() |
«» | socket_object:accept() |
teardown | socket_object:shutdown() |
«» | socket_object:close() |
error checking | socket_object:error() |
«» | socket_object:errno() |
information | socket.getaddrinfo() |
«» | socket_object:getsockopt() |
«» | socket_object:peer() |
«» | socket_object:name() |
state checking | socket_object:readable() |
«» | socket_object:writable() |
«» | socket_object:wait() |
«» | socket.iowait() |
Typically a socket session will begin with the setup functions, will set one or more flags, will have a loop with sending and receiving functions, will end with the teardown functions – as an example at the end of this section will show. Throughout, there may be error-checking and waiting functions for synchronization. To prevent a fiber containing socket functions from «blocking» other fibers, the implicit yield rules will cause a yield so that other processes may take over, as is the norm for cooperative multitasking.
For all examples in this section the socket name will be sock and
the function invocations will look like sock:function_name(...)
.
-
socket.
__call
(domain, type, protocol)¶ Create a new TCP or UDP socket. The argument values are the same as in the Linux socket(2) man page.
Return: an unconnected socket, or nil. Rtype: userdata Example:
socket('AF_INET', 'SOCK_STREAM', 'tcp')
-
socket.
tcp_connect
(host[, port[, timeout]])¶ Connect a socket to a remote host.
Параметры: - host (string) – URL or IP address
- port (number) – port number
- timeout (number) – timeout
Return: a connected socket, if no error.
Rtype: userdata
Example:
socket.tcp_connect('127.0.0.1', 3301)
-
socket.
getaddrinfo
(host, type[, {option-list}])¶ The
socket.getaddrinfo()
function is useful for finding information about a remote site so that the correct arguments forsock:sysconnect()
can be passed.Return: A table containing these fields: «host», «family», «type», «protocol», «port». Rtype: table Example:
socket.getaddrinfo('tarantool.org', 'http')
will return variable information such as--- - - host: 188.93.56.70 family: AF_INET type: SOCK_STREAM protocol: tcp port: 80 - host: 188.93.56.70 family: AF_INET type: SOCK_DGRAM protocol: udp port: 80 ...
-
socket.
tcp_server
(host, port, handler-function[, timeout])¶ The
socket.tcp_server()
function makes Tarantool act as a server that can accept connections. Usually the same objective is accomplished with box.cfg{listen=…}.Параметры: - host (string) – host name or IP
- port (number) – host port, may be 0
- handler (function/table) – what to execute when a connection occurs
- timeout (number) – number of seconds to wait before timing out
The handler-function parameter may be a function name (for example
function_55
), a function declaration (for examplefunction () print('!') end
), or a table including handler = function (for example{handler=function_55, name='A'}
).Example:
socket.tcp_server('localhost', 3302, function () end)
-
object
socket_object
¶ -
socket_object:
sysconnect
(host, port)¶ Connect an existing socket to a remote host. The argument values are the same as in tcp_connect(). The host must be an IP address.
- Parameters:
- Either:
- host - a string representation of an IPv4 address or an IPv6 address;
- port - a number.
- Or:
- host - a string containing «unix/»;
- port - a string containing a path to a unix socket.
- Or:
- host - a number, 0 (zero), meaning «all local interfaces»;
- port - a number. If a port number is 0 (zero), the socket will be bound to a random local port.
Return: the socket object value may change if sysconnect() succeeds. Rtype: boolean Example:
socket = require('socket') sock = socket('AF_INET', 'SOCK_STREAM', 'tcp') sock:sysconnect(0, 3301)
-
socket_object:
send
(data)¶ -
socket_object:
write
(data)¶ Send data over a connected socket.
Параметры: - data (string) –
Return: the number of bytes sent.
Rtype: number
Possible errors: nil on error.
-
socket_object:
syswrite
(size)¶ Write as much as possible data to the socket buffer if non-blocking. Rarely used. For details see this description.
-
socket_object:
recv
(size)¶ Read
size
bytes from a connected socket. An internal read-ahead buffer is used to reduce the cost of this call.Параметры: - size (integer) –
Return: a string of the requested length on success.
Rtype: string
Possible errors: On error, returns an empty string, followed by status, errno, errstr. In case the writing side has closed its end, returns the remainder read from the socket (possibly an empty string), followed by «eof» status.
-
socket_object:
read
(limit[, timeout])¶ -
socket_object:
read
(delimiter[, timeout]) -
socket_object:
read
({limit=limit}[, timeout]) -
socket_object:
read
({delimiter=delimiter}[, timeout]) -
socket_object:
read
({limit=limit, delimiter=delimiter}[, timeout]) Read from a connected socket until some condition is true, and return the bytes that were read. Reading goes on until
limit
bytes have been read, or a delimiter has been read, or a timeout has expired.Параметры: - limit (integer) – maximum number of bytes to read, for example 50 means «stop after 50 bytes»
- delimiter (string) – separator for example „?“ means «stop after a question mark»
- timeout (number) – maximum number of seconds to wait for example 50 means «stop after 50 seconds».
Return: an empty string if there is nothing more to read, or a nil value if error, or a string up to
limit
bytes long, which may include the bytes that matched thedelimiter
expression.Rtype: string
-
socket_object:
sysread
(size)¶ Return data from the socket buffer if non-blocking. In case the socket is blocking,
sysread()
can block the calling process. Rarely used. For details, see also this description.Параметры: - size (integer) – maximum number of bytes to read, for example 50 means «stop after 50 bytes»
Return: an empty string if there is nothing more to read, or a nil value if error, or a string up to
size
bytes long.Rtype: string
-
socket_object:
bind
(host[, port])¶ Bind a socket to the given host/port. A UDP socket after binding can be used to receive data (see socket_object.recvfrom). A TCP socket can be used to accept new connections, after it has been put in listen mode.
Параметры: - host –
- port –
Return: a socket object on success
Rtype: userdata
Possible errors: Returns nil, status, errno, errstr on error.
-
socket_object:
listen
(backlog)¶ Start listening for incoming connections.
Параметры: - backlog – On Linux the listen
backlog
backlog may be from /proc/sys/net/core/somaxconn, on BSD the backlog may beSOMAXCONN
.
Return: true for success, false for error.
Rtype: boolean.
- backlog – On Linux the listen
-
socket_object:
accept
()¶ Accept a new client connection and create a new connected socket. It is good practice to set the socket’s blocking mode explicitly after accepting.
Return: new socket if success. Rtype: userdata Possible errors: nil.
-
socket_object:
sendto
(host, port, data)¶ Send a message on a UDP socket to a specified host.
Параметры: - host (string) –
- port (number) –
- data (string) –
Return: the number of bytes sent.
Rtype: number
Possible errors: on error, returns status, errno, errstr.
-
socket_object:
recvfrom
(limit)¶ Receive a message on a UDP socket.
Параметры: - limit (integer) –
Return: message, a table containing «host», «family» and «port» fields.
Rtype: string, table
Possible errors: on error, returns status, errno, errstr.
Example:
After
message_content, message_sender = recvfrom(1)
the value ofmessage_content
might be a string containing „X“ and the value ofmessage_sender
might be a table containingmessage_sender.host = '18.44.0.1' message_sender.family = 'AF_INET' message_sender.port = 43065
-
socket_object:
shutdown
(how)¶ Shutdown a reading end, a writing end, or both ends of a socket.
Параметры: - how – socket.SHUT_RD, socket.SHUT_WR, or socket.SHUT_RDWR.
Return: true or false.
Rtype: boolean
-
socket_object:
close
()¶ Close (destroy) a socket. A closed socket should not be used any more. A socket is closed automatically when its userdata is garbage collected by Lua.
Return: true on success, false on error. For example, if sock is already closed, sock:close() returns false. Rtype: boolean
-
socket_object:
error
()¶ -
socket_object:
errno
()¶ Retrieve information about the last error that occurred on a socket, if any. Errors do not cause throwing of exceptions so these functions are usually necessary.
Return: result for sock:errno()
, result forsock:error()
. If there is no error, thensock:errno()
will return 0 andsock:error()
.Rtype: number, string
-
socket_object:
setsockopt
(level, name, value)¶ Set socket flags. The argument values are the same as in the Linux getsockopt(2) man page. The ones that Tarantool accepts are:
- SO_ACCEPTCONN
- SO_BINDTODEVICE
- SO_BROADCAST
- 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 SO_LINGER is done with
sock:linger(active)
.
-
socket_object:
getsockopt
(level, name)¶ Get socket flags. For a list of possible flags see
sock:setsockopt()
.
-
socket_object:
linger
([active])¶ Set or clear the SO_LINGER flag. For a description of the flag, see the Linux man page.
Параметры: - active (boolean) –
Return: new active and timeout values.
-
socket_object:
nonblock
([flag])¶ sock:nonblock()
returns the current flag value.sock:nonblock(false)
sets the flag to false and returns false.sock:nonblock(true)
sets the flag to true and returns true.
This function may be useful before invoking a function which might otherwise block indefinitely.
-
socket_object:
readable
([timeout])¶ Wait until something is readable, or until a timeout value expires.
Return: true if the socket is now readable, false if timeout expired;
-
socket_object:
writable
([timeout])¶ Wait until something is writable, or until a timeout value expires.
Return: true if the socket is now writable, false if timeout expired;
-
socket_object:
wait
([timeout])¶ Wait until something is either readable or writable, or until a timeout value expires.
Return: „R“ if the socket is now readable, „W“ if the socket is now writable, „RW“ if the socket is now both readable and writable, „“ (empty string) if timeout expired;
-
socket_object:
name
()¶ The
sock:name()
function is used to get information about the near side of the connection. If a socket was bound toxyz.com:45
, thensock:name
will return information about[host:xyz.com, port:45]
. The equivalent POSIX function isgetsockname()
.Return: A table containing these fields: «host», «family», «type», «protocol», «port». Rtype: table
-
socket_object:
peer
()¶ The
sock:peer()
function is used to get information about the far side of a connection. If a TCP connection has been made to a distant hosttarantool.org:80
,sock:peer()
will return information about[host:tarantool.org, port:80]
. The equivalent POSIX function isgetpeername()
.Return: A table containing these fields: «host», «family», «type», «protocol», «port». Rtype: table
-
-
socket.
iowait
(fd, read-or-write-flags[, timeout])¶ The
socket.iowait()
function is used to wait until read-or-write activity occurs for a file descriptor.Параметры: - fd – file descriptor
- read-or-write-flags – „R“ or 1 = read, „W“ or 2 = write, „RW“ or 3 = read|write.
- timeout – number of seconds to wait
If the fd parameter is nil, then there will be a sleep until the timeout. If the timeout parameter is nil or unspecified, then timeout is infinite.
Ordinarily the return value is the activity that occurred („R“ or „W“ or „RW“ or 1 or 2 or 3). If the timeout period goes by without any reading or writing, the return is an error = ETIMEDOUT.
Example:
socket.iowait(sock:fd(), 'r', 1.11)
Примеры:¶
Use of a TCP socket over the Internet¶
In this example a connection is made over the internet between a Tarantool
instance and tarantool.org, then an HTTP «head» message is sent, and a response
is received: «HTTP/1.1 200 OK
» or something else if the site has moved.
This is not a useful way to communicate
with this particular site, but shows that the system works.
tarantool> socket = require('socket')
---
...
tarantool> sock = socket.tcp_connect('tarantool.org', 80)
---
...
tarantool> type(sock)
---
- table
...
tarantool> sock:error()
---
- null
...
tarantool> sock:send("HEAD / HTTP/1.0\r\nHost: tarantool.org\r\n\r\n")
---
- 40
...
tarantool> sock:read(17)
---
- HTTP/1.1 302 Move
...
tarantool> sock:close()
---
- true
...
Use of a UDP socket on localhost¶
Here is an example with datagrams. Set up two connections on 127.0.0.1
(localhost): sock_1
and sock_2
. Using sock_2
, send a message
to sock_1
. Using sock_1
, receive a message. Display the received
message. Close both connections.
This is not a useful way for a
computer to communicate with itself, but shows that the system works.
tarantool> socket = require('socket')
---
...
tarantool> sock_1 = socket('AF_INET', 'SOCK_DGRAM', 'udp')
---
...
tarantool> sock_1:bind('127.0.0.1')
---
- true
...
tarantool> sock_2 = socket('AF_INET', 'SOCK_DGRAM', 'udp')
---
...
tarantool> sock_2:sendto('127.0.0.1', sock_1:name().port,'X')
---
- true
...
tarantool> message = sock_1:recvfrom()
---
...
tarantool> message
---
- X
...
tarantool> sock_1:close()
---
- true
...
tarantool> sock_2:close()
---
- true
...
Use tcp_server to accept file contents sent with socat¶
Here is an example of the tcp_server function, reading strings from the client and printing them. On the client side, the Linux socat utility will be used to ship a whole file for the tcp_server function to read.
Start two shells. The first shell will be a server instance. The second shell will be the client.
On the first shell, start Tarantool and say:
box.cfg{}
socket = require('socket')
socket.tcp_server('0.0.0.0', 3302, function(s)
while true do
local request
request = s:read("\n");
if request == "" or request == nil then
break
end
print(request)
end
end)
The above code means: use tcp_server() to wait for a connection from any host on port 3302. When it happens, enter a loop that reads on the socket and prints what it reads. The «delimiter» for the read function is «\n» so each read() will read a string as far as the next line feed, including the line feed.
On the second shell, create a file that contains a few lines. The contents don’t matter. Suppose the first line contains A, the second line contains B, the third line contains C. Call this file «tmp.txt».
On the second shell, use the socat utility to ship the tmp.txt file to the server instance’s host and port:
$ socat TCP:localhost:3302 ./tmp.txt
Now watch what happens on the first shell. The strings «A», «B», «C» are printed.