luasocket/doc/stream.html
2003-08-31 01:00:15 +00:00

174 lines
5.0 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>LuaSocket: Network support for the Lua language</title>
<link rel="stylesheet" href="reference.css" type="text/css">
</head>
<body>
<!-- header +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<div class=header>
<hr>
<center>
<table summary="LuaSocket logo">
<tr><td align=center><a href="http://www.lua.org">
<img border=0 alt="LuaSocket" src="luasocket.png">
</a></td></tr>
<tr><td align=center valign=top>Network support for the Lua language
</td></tr>
</table>
<p class=bar>
<a href="home.html">home</a> &middot;
<a href="home.html#download">download</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<a href="reference.html">reference</a>
</p>
</center>
<hr>
</div>
<!-- stream ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<h2 id=stream>Streaming with Callbacks</h2>
<p>
HTTP and FTP transfers sometimes involve large amounts of information.
Sometimes an application needs to generate outgoing data in real time,
or needs to process incoming information as it is being received. To
address these problems, LuaSocket allows HTTP message bodies and FTP
file contents to be received or sent through the callback mechanism
outlined below.
</p>
<p>
Instead of returning the entire contents of a FTP file or HTTP message
body as strings to the Lua application, the library allows the user to
provide a <em>receive callback</em> that will be called with successive
chunks of data, as the data becomes available. Conversely, the <em>send
callbacks</em> should be used when data needed by LuaSocket
is generated incrementally by the application.
</p>
<!-- tohostname +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<p class=name id=receive_cb>
<b>receive_cb(</b>chunk, err<b>)</b>
</p>
<p class=description>
The callback provided by the user will be repeatedly called by the
library whenever new data is available. Each time it is called, the
callback receives successive chunks of downloaded data.
</p>
<p class=parameters>
<tt>Chunk</tt> contains the current chunk of data.
When the transmission is over, the function is called with an
empty string (i.e.&nbsp;<tt>""</tt>) as the <tt>chunk</tt>. If an error occurs, the
function receives <tt>nil</tt> as <tt>chunk</tt> and an error message as
<tt>err</tt>.
</p>
<p class=return>
The callback can abort transmission by returning
<tt>nil</tt> as its first return value. In that case, it can also return
an error message. Any non-<tt>nil</tt> return value proceeds with the
transmission.
</p>
<pre class=example>
-- The implementation of socket.callback.receive_concat
function Public.receive_concat(concat)
concat = concat or socket.concat.create()
local callback = function(chunk, err)
-- if not finished, add chunk
if chunk and chunk ~= "" then
concat:addstring(chunk)
return 1
end
end
return callback, concat
end
</pre>
<!-- send_cb ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<p class=name>
<b>send_cb()</b>
</p>
<p class=description>
The callback provided by the user will be repeatedly called whenever the
library needs more data to be sent.
</p>
<p class=return>
Each time the callback is called, it
should return the next part of the information the library is expecting,
followed by the total number of bytes to be sent.
The callback can abort
the process at any time by returning <tt>nil</tt> followed by an
optional error message.
</p>
<p class=note>
Note: The need for the second return value comes from the fact that, with
the HTTP protocol for instance, the library needs to know in advance the
total number of bytes that will be sent.
</p>
<pre class=example>
-- The implementation of socket.callback.send_file
function Public.send_file(file)
local callback
-- if successfull, return the callback that reads from the file
if file then
-- get total size
local size = file:seek("end")
-- go back to start of file
file:seek("set")
callback = function()
-- send next block of data
local chunk = file:read(Public.BLOCKSIZE)
if not chunk then file:close() end
return chunk, size
end
-- else, return a callback that just aborts the transfer
else
callback = function()
-- just abort
return nil, "unable to open file"
end
end
return callback, file
end
</pre>
<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<div class=footer>
<hr>
<center>
<p class=bar>
<a href="home.html">home</a> &middot;
<a href="home.html#down">download</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<a href="reference.html">reference</a>
</p>
<p>
<small>
Last modified by Diego Nehab on <br>
Sat Aug 9 01:00:41 PDT 2003
</small>
</p>
</center>
</div>
</body>
</html>