aboutsummaryrefslogtreecommitdiff
path: root/doc/stream.html
blob: 585ad18a0e1f326adfa478260d3e6fa773afe808 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
<!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, FTP, and SMTP 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 and SMTP 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 an entity 
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> can be used when the application wants to incrementally 
provide LuaSocket with the data to be sent. 
</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 <b><tt>nil</tt></b> 
as <tt>chunk</tt> and  an error  message in <tt>err</tt>. 
</p>

<p class=return>
The callback  can abort transmission by returning <b><tt>nil</tt></b> as its first
return value, and an optional error  message as the
second return value. If the application wants to continue receiving
data, the function should return non-<b><tt>nil</tt></b> as it's first return
value. In this case, the function can optionally return a 
new callback function, to replace itself, as the second return value.  
</p>

<p class=note>
Note: The <tt>callback</tt> module provides several standard receive callbacks, including the following:
</p>

<pre class=example>
function 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>

<p class=note>
This function creates a new receive callback that concatenates all
received chunks into a the same concat object, which can later be 
queried for its contents.
</p>

<!-- 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 chunk of data.  It
can optionally return, as it's second return value, a new callback to replace
itself.  The callback can abort the  process  at any  time  by  returning
<b><tt>nil</tt></b> followed  by  an optional error message. 
</p>

<p class=note>
Note: Below is the implementation of the <tt>callback.send.file</tt> 
function. Given an open file handle, it returns a send callback that will send the contents of that file, chunk by chunk.
</p>

<pre class=example>
function send.file(file, io_err)
    -- if successful, return the callback that reads from the file
    if file then
        return function()
            -- send next block of data
            return (file:read(BLOCKSIZE)) or ""
        end
    -- else, return a callback that just aborts the transfer
    else return fail(io_err or "unable to open file") end
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>