The Lua language
LuaSocket
IPv4 Socket support for the Lua language

what is · introduction · current version · functions · protocols


Contents


What is LuaSocket?

LuaSocket is a Lua extension library that provides support for TCP and UDP socket layer within the Lua language. The library also provides support for SMTP (sending e-mails), HTTP (www) and FTP (uploading and downloading files).

It can be used by any Lua application desiring access to network communication on the Internet, once it has been properly linked with and initialized by the interpreter running the application. The code has been tested and runs well both on Windows and on Unix Platforms.

The library is available under the same terms as the Lua language, that is, it can be used at no cost for both academic and commercial purposes.

Copyright (C) 2000 TeCGraf, PUC-Rio. All rights reserved.
Author: Diego Nehab

Introduction

Below is a little introduction on how to get the library up and running with your applications and a little introduction on network programming with LuaSocket.

How to initialize the library

To have the library functions made available to a Lua script, the interpreter running the script must be linked to the luasocket library, and to whatever libraries the OS in use requires for socket programming. The functions are registered in the Lua state given as the parameter to the function lua_socketlibopen, the only C function exported by the library. The scripts can then use all registered functions.

Network programming with LuaSocket

Bringing network support into the Lua language brings out the choice between having an API similar to the C socket API or creating a new transport layer abstraction. Having an API similar to the C API would make things easier for those used to socket programming. On the other hand, the simplicity of the Lua language would be lost. We ended up with something in between.

One of the major differences the API is the timeout control provided by the library. All I/O operations are blocking by default. In other words, the send, receive and accept functions will block the caller application until the operation is completed (if ever). The application can, however, specify upper limits on the time it can be blocked by LuaSocket ("return" timeout), or it can specify a time limit on the time LuaSocket can be blocked by the OS ("blocked" timeout) or a combination of the two. Remember that each LuaSocket call performs several OS calls, so that the two timeout values are not equivalent.

Another major difference is the receive pattern capability. Applications can read data from a TCP client socket line by line, chunk by chunk or until the connection is closed. All I/O reads are buffered and the performance difference between different receive patterns is negligible.

Finally, most functions accept both IP addresses and host names. In case a host name is given, the library queries the resolver and tries all returned IP addresses until one succeeds or all fail. IP addresses are directly encoded and are therefore more efficient. The toip and tohostname functions are provided to convert between host names and IP addresses.

Socket objects are represented as tables in the Lua language. Different socket types accept different operations. These operations are available both as stand-alone global functions and as table methods of the socket objects. For example, the function call send(socket,"test") is equivalent to the function call socket:send("test"), where socket is a client socket object.

TCP programming

TCP is a reliable stream protocol. In other words, applications send and receive data as an error free stream of bytes. Data is split in one end and reassembled transparently on the other end. There are no boundaries in the data transfers. The library distinguishes two types of TCP sockets: client sockets and server sockets.

Client sockets are used to exchange data between two applications over the Internet. Client sockets are created by the connect function or returned by the accept server socket method. Applications can call the methods send and receive to send and receive data. The other methods available for client socket objects are timeout and close.

Server sockets are created by the bind function and are associated with a address and port on a the local. Applications use the accept method to wait for a client connection on a server socket. Once a connection is established, a client socket object is returned representing this connection. The other methods available for server socket objects are getsockname, getpeername, timeout and close.

UDP programming

UDP is a non-reliable datagram protocol. In other words, applications send and receive data as independent blocks, which are not guaranteed to reach the other end. Even when they reach the other side, they are not guaranteed to be error free. Data transfers are atomic, sending or receiving one datagram at a time. Reading only part of a datagram discards the rest, so that the next read operation will act on a different datagram. The gain lies in simplicity and performance.

An UDP socket object is created by the udpcreate function. UDP sockets do not need to be connected before use. The method sendto can be used immediately after creation to send a datagram to any UDP (ip, port) pair. Host names are not allowed for performance reasons. Methods receive and receivefrom can be used to retrieve datagrams, the latter returning the ip and port of the sender as extra return values.

When communication is performed with a single peer, an application can call the setpeername method to specify a partner. The method send can be used to send data directly to the peer, and methods receive and receivefrom only return datagrams originating from that peer. There is about 30% performance gain due to this practice.

To associate an UDP socket with a local address, an application calls the setsockname function. The other methods available for UDP sockets are getpeername, getsockname, timeout and close.

Current Version

LuaSocket version 1.2 is now available for download! It is compatible with Lua 4.0 and has been tested on Windows 98, Windows 2000, Linux, AIX, and SunOS.

What's New

There have been some improvements since version 1.1, mainly motivated by feedback from the Lua community:

Incompatibilities with Previous Versions

There server method listen has been removed from the library. The backlog server socket value, when the default value of 1 is not satisfactory, MUST be assigned at bind time.

Download

The library can be downloaded in source code here:

luasocket-1.2.tar.gz
luasocket-1.2.zip

Function Reference

All the functions of the API are described below. Several examples are given in the distribution, including the automated tests and the full implementation of the protocols FTP, SMTP and HTTP.

Note that although some function names are overloaded, documentation is provided separately for TCP and UDP sockets.

TCP sockets

accept(socket)

Creates and returns a TCP client socket object, representing a client attempting connection on the server socket. The function blocks until a remote connection attempt is detected or until the timeout condition is met.

bind(address, port [, backlog])

Creates a new TCP server socket and binds it to (address, port) on the local host. Address can be an IP address or a host name. If address is '*', the system binds to all local interfaces (INADDR_ANY). If port is 0, the system automatically chooses an ephemeral port. The optional parameter backlog (default value 1) specifies the number of client connections that can be queued waiting for service. If the queue is full and another client attempts connection, the connection is refused. In case of success, the function returns a server socket, on which the operations accept, close, getsockname and listen are permitted. In case of error, the function returns nil followed by a string describing the error.

close(socket)

Closes the socket socket. No further operations are allowed on a closed socket. The local address to which it is bound is made available to other applications.

Note: It is important to close all used sockets once they are not needed, since, in many systems, each socket uses a file descriptor, which are a limited system resource.

connect(address, port)

Creates a new TCP client socket and tries to connect to (address, port). Address can be an IP address or a host name. In case of success, the function returns a client socket on which the operations send, receive and close are permitted. In case of error, the function returns nil followed by a string describing the error.

getpeername(socket)

Returns the IP address and port of the peer connected to the TCP client socket or nil in case of error. Note that it makes no sense to call getpeername on a server socket object.

poll(socket, operation)

Determines if socket is ready for operation, which can be:

The function returns 1 if socket is ready, and nil otherwise. The poll function returns imediately.

Important Note: a know bug in WinSock prevents poll from working properly on non-blocking TCP sockets. The function may return 1 on operation '*s' when the socket is not ready for sending.

Note: simply calling poll with operation '*r' on a server socket before a call to accept does not guarantee accept will return. Use the timeout server socket method instead, which DOES guarantee that.

getsockname(socket)

Returns the local IP address and port of the TCP socket or nil in case of error.

receive(socket [, pattern1, pattern2, ... patternN])

Receives pattern1, pattern2, ... patternN from the client socket. A pattern can be one of the following:

The function returns one string for each pattern, followed by a single error code that can be nil in case of success, the string 'closed' in case the connection was closed before the transmission was complete or the string 'timeout' in case there was a timeout during the operation. The difference in performance between all patterns is negligible.

send(socket, string1 [, string2, ... stringN])

Sends the strings string1, string2, ... stringN through the client socket socket. The function returns an error code, which is nil in case of success, the string 'closed' in case the connection was closed before the transmission was complete or the string 'timeout' in case there was a timeout during the operation. After the error code, the function returns the number of bytes accepted by the transport layer.

timeout(socket, value [, mode])

Changes the timeout values for the socket socket. By default, all I/O operations are blocking. That is, any call to the functions send and receive will block indefinitely, until the operation completes. The timeout function defines a limit on the amount of time the functions can block, specified as the value parameter, in seconds. There are two timeout modes and both can be used together for fine tuning:

The nil timeout value allows operations to block indefinitely. Negative timeout values have the same effect.

Note: although timeout values have millisecond precision, large blocks can cause I/O functions not to respect timeout values due to the time the library takes to transfer blocks to and from the kernel and to and from the Lua interpreter.

UDP sockets

close(socket)

Closes the socket socket. No further operations are allowed on a closed socket. The local address to which it is bound is made available to other applications.

Note: It is important to close all used sockets once they are not needed, since, in many systems, each socket uses a file descriptor, which are a limited system resource.

getpeername(socket)

Returns the IP address and port of the peer of the UDP socket. The function will fail unless a peer has been set with a call to setpeername.

getsockname(socket)

Returns the local IP address and port of the TCP socket or nil in case of error.

Note: UDP sockets are not bound to any address until setsockname or the first sendto method is called (in which case it is bound to an ephemeral port and the wildcard address). The local address will not change thereafter.

poll(socket, operation)

Determines if socket is ready for operation, which can be:

The function returns 1 if socket is ready, and nil otherwise. The poll function returns imediately.

receive(socket [, number])

Receives a datagram from the UDP socket socket with up to number bytes. If there are more than number bytes available in the datagram, the remaining are discarded. If there are less then number bytes available in the current datagram, the available bytes are returned. If number is omitted, the maximum datagram size is used. In case of timeout, the function returns nil followed by the string 'timeout'. In case the transmission failed, the function returns nil followed by the string 'refused'.

receivefrom(socket [, number])

Works exactly as the receive function, except it returns the sender ip and port as extra return values and therefore is slightly less efficient.

send(socket, string)

Sends string to the UDP peer of socket socket. The method setpeername MUST have been called on socket. If successful, the function returns nil. In case of timeout, the function returns the string 'timeout'. In case the transmission failed, the function returns the string 'refused'.

sendto(socket, string, ip, port)

Sends string to (ip, port). In case of timeout, the function returns the string 'timeout'. Ip MUST be an IP address, for performance reasons. In case the transmission failed, the function returns the string 'refused'.

setpeername(socket, address, port)

Sets the socket UDP peer to (address, port). Address can be an IP address or a host name. After a call to setpeername, the send and receive MUST be used instead of sendto and receivefrom. Outgoing datagrams will be sent to the specified peer, and datagrams received from other peers will be discarded by the OS. Since the address of the peer does not have to be passed to and from the OS, this practice is recommended when the same peer is used for several transmissions and can lead to up to 30% performance gains.

setsockname(socket, address, port)

Binds the UDP socket to a local address (address, port). Address can be an IP address or a host name. If address is '*' the system binds to all local interfaces (INADDR_ANY). If port is 0, the system chooses an ephemeral port. If successful, the function returns nil. In case of error, the function returns an error message.

timeout(socket, value)

Changes the timeout value for the socket socket. By default, all operations are blocking. The timeout function defines a limit on the amount of time the functions can block, specified as the value parameter, in seconds. The nil timeout value allows operations to block indefinitely. Negative timeout values have the same effect.

Note: there is no send buffer on an UDP socket. Therefore, a send operation on an UDP socket should never block, regardless of the timeout value. Receive operations, however, can block the application.

udpsocket()

Creates and returns an UDP socket object, on which the methods close, getpeername, getsockname, receive, receivefrom, send, sendto, setpeername, setsockname and timeout can be used. In case of error, the function returns nil and an error message.

DNS Services

The following functions can be used to convert between host names and IP addresses. All information returned by the resolver is returned by these functions, as a table in the form:

resolved = {
  ["name"] = "canonic-name",
  ["alias"] = alias-list,
  ["ip"] = ip-address-list
}
Note that the alias list can be empty.

tohostname(address)

Returns a string with the canonic host name of given address, followed by a table with all information returned by the resolver. Address can be an IP address or host name. In casee of error, the function returns nil followed by an error message.

toip(address)

Returns a string with the first IP address found for address, followed by a table with all information returned by the resolver. Address can be an IP address or host name. In case of error, the function returns nil followed by an error message.

Protocol Reference

Besides IPv4 transport layer support, the LuaSocket toolkit offers straightforward support for the HTTP, SMTP and FTP protocols. The support is implemented in the Lua language and is distributed in source code as three separate modules.

SMTP

The module smtp.lua provides functionality to send e-mail messages to a SMTP mail server. The implementation conforms to RFC 821.

MIME Headers are represented as a table in the form:

headers = {
  ["field-1-name"] = "field-1-value",
  ["field-2-name"] = "field-2-value",
  ["field-3-name"] = "field-3-value",
         ...               ...
  ["field-n-name"] = "field-n-value"
}
The module exports two functions:

smtp_mail(from, rcpt, headers, body, server)

Sends a message to recipient list rcpt, a lua table. The sender is given by the e-mail address from. The message is composed by the optional MIME Headers headers and text body. The message is sent using the server server. If successful, the function returns nil, otherwise an error message is returned.

Examples:

headers = {
  to = "fulano@tecgraf.puc-rio.br, beltrano@tecgraf.puc-rio.br",
  subject = "LuaSocket test message"
}
from = "luasocket@tecgraf.puc-rio.br"
rcpt = {
  "fulano@tecgraf.puc-rio.br",
  "beltrano@tecgraf.puc-rio.br",
  "sicrano@tecgraf.puc-rio.br"
}
body = "This is a test message. Please ignore."
server = "local"
-- connects to server "local" and sends a message to users 
-- "fulano@tecgraf.puc-rio.br" and "beltrano@tecgraf.puc-rio.br"
-- "sicrano@tecgraf.puc-rio.br" receives a 'blind carbon copy' of the message.
e = smtp_mail(from, rcpt, headers, body, server)

mail {
  to=tolist,
  from=from,
  subject=subject,
  message=message,
  cc=cclist,
  bcc=bcclist,
  mailserver=server
}

The mail function, for compatibility, implements the same interface as that of CGILua 3.2, except the mailserver parameter is mandatory.

to:A comma-separated list of the e-mails of the recipients of the message.
from:The email of the sender.
subject: Optional message subject.
message: Optional message body.
cc: An optional comma-separated list of the e-mails of "carbon-copy" recipients.
bcc: An optional comma-separated list of the e-mails of the "blind carbon-copy" recipients.
mailserver: Address of SMTP server to be used.

The function returns nil if the message was sent successfully. In case of error, an error message is returned.

HTTP

The module http.lua provides functionality to download an URL from an HTTP server. The implementation conforms to the HTTP/1.1 standard, RFC 2068.

URLs MUST conform to RFC 1738, that is, an URL is a string in the form:

[http://][<user>[:<password>]@]<>[:<port>][/<path>] 
MIME Headers are represented as a table in the form:

headers = {
  ["field-1-name"] = "field-1-value",
  ["field-2-name"] = "field-2-value",
  ["field-3-name"] = "field-3-value",
         ...               ...
  ["field-n-name"] = "field-n-value"
}
Field names are case insensitive (as specified by the standard) and all API functions work with lowercase field names. Field values are left unmodified.

The module exports three functions:

http_request(method, url [, headers, body])

Performs the generic HTTP request using method on url sending the request headers and message body along with the request. If successful, the function returns the body of the reply, a table with mime headers and the HTTP status returned by the server. In case of error, the function returns whatever it managed to retrieve (nil values representing failure) and and an error message describing the error. If <user> and <password> are provided in the URL, the function uses the Basic Authentication Scheme (see note) to retrieve the document.

http_get(url [, headers])

Calls http_request with method 'GET'.

Examples:

-- connect to server "www.tecgraf.puc-rio.br" and retrieves this manual
-- file from "~diego/luasocket/manual.html"
f, m, s, e = http_get("http://www.tecgraf.puc-rio.br/~diego/luasocket/manual.html")

-- connect to server "www.tecgraf.puc-rio.br" and tries to retrieve
-- "~diego/auth/index.html". Fails because authentication is needed.
f, m, s, e = http_get("http://www.tecgraf.puc-rio.br/~diego/auth/index.html")
-- s returns with value "401 Authentication Required"

Note: Some URLs are protected by their servers from anonymous download. For those URLs, the server must receive some sort of authentication along with the request or it will deny download and return status "401 Authentication Required".

The HTTP/1.1 standard defines two authentication methods: the Basic Authentication Scheme and the Digest Authentication Scheme, both explained in detail in RFC 2068.

The Basic Authentication Scheme sends <user> and <password> unencrypted to the server and is therefore considered unsafe. Unfortunately, by the time of this implementation, the wide majority of servers and browsers support the Basic Scheme only. Therefore, this is the method used by the toolkit whenever authentication is required.

Example:

-- connect to server "www.tecgraf.puc-rio.br" and tries to retrieve
-- "~diego/auth/index.html", using the provided name and password to
-- authenticate the request
f, m, s, e = http_get("http://diego:nehab@www.tecgraf.puc-rio.br/~diego/auth/index.html")

-- alternatively, one could fill the appropriate header and authenticate
-- the request directly. both calls are equivalent
h = {authentication = "Basic " .. base64("diego:nehab")}
f, m, s, e = http_get("http://www.tecgraf.puc-rio.br/~diego/auth/index.html", h)

http_post(url, body [, headers])

Calls http_request with method 'POST' sending body along with the request.

FTP

The module ftp.lua provides functions to download and upload files from and to FTP servers. The implementation conforms to RFC 959.

URLs MUST conform to RFC 1738, that is, an URL is a string in the form:

[ftp://][<user>[:<password>]@]<>[:<port>][/<path>] 
The module exports two functions:

ftp_get(url [, type])

Downloads the URL url using transfer type type and returns it as a string.

The parameter type can receive values 'a' (ascii, the default) or 'b' (binary) and determines the transfer type. If <path> ends with a '/', a directory listing of <path> is returned. If successful, the function returns the file contents as a string. In case of error, the function returns nil and an error message describing the error.

If no <user> is provided, the function tries to log in as 'anonymous'.

Examples:

-- log as user "anonymous" on server "ftp.tecgraf.puc-rio.br"
-- go to directory "pub/lua" and get file "lua.tar.gz" as binary.
f, e = ftp_get("ftp://ftp.tecgraf.puc-rio.br/pub/lua/lua.tar.gz", "b")

-- log as user "anonymous" on server "ftp.tecgraf.puc-rio.br"
-- go to director "pub" and retrieve directory listing of directory "lua"
f, e = ftp_get("ftp://ftp.tecgraf.puc-rio.br/pub/lua/")

-- log as user "diego", password "nehab", on server "derain.tecgraf.puc-rio.br"
-- go to directory "tec/luasocket/html" and retrieve file "manual.html"
-- (actually, fails because of wrong password :-)
f, e = ftp_get("ftp://diego:nehab@derain.tecgraf.puc-rio.br/tec/luasocket/html/manual.html")

ftp_put(url, data [, type])

Stores a file at url with contents given by the string data and using transfer type type.

The parameter type can receive values 'a' (ascii, the default) or 'b' (binary) and determines the transfer type. If successful, the function returns nil. In case of error, the function returns a string describing the error.

If no <user> is provided, the function tries to log in as anonymous.

Examples:

-- log as user "anonymous" on server "ftp.free.org" and store file
-- "hello" with contents "hello world!" on current directory
e = ftp_put("ftp://ftp.free.org/hello", "hello world!")

what is · introduction · current version · functions · protocols


Created with Vim and Best Viewed on Any Browser
Last modified by Diego Nehab on
Thu Jan 25 16:11:36 EDT 2001