diff options
| author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-07-18 22:56:14 +0000 |
|---|---|---|
| committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-07-18 22:56:14 +0000 |
| commit | c8b402e00442cd249397d4d33d2723a1f08a8108 (patch) | |
| tree | d72a1ace55b42aa9d41c741fa2f757d92fad6592 | |
| parent | e4e2223cff658a7016724a625ebbd3dacb92a8f9 (diff) | |
| download | luasocket-c8b402e00442cd249397d4d33d2723a1f08a8108.tar.gz luasocket-c8b402e00442cd249397d4d33d2723a1f08a8108.tar.bz2 luasocket-c8b402e00442cd249397d4d33d2723a1f08a8108.zip | |
Changed send function.
| -rw-r--r-- | FIX | 4 | ||||
| -rw-r--r-- | TODO | 3 | ||||
| -rw-r--r-- | doc/introduction.html | 2 | ||||
| -rw-r--r-- | doc/tcp.html | 35 | ||||
| -rw-r--r-- | src/buffer.c | 23 | ||||
| -rw-r--r-- | src/wsocket.c | 2 | ||||
| -rw-r--r-- | test/testclnt.lua | 86 | ||||
| -rw-r--r-- | test/testsrvr.lua | 33 |
8 files changed, 118 insertions, 70 deletions
| @@ -1,3 +1,7 @@ | |||
| 1 | UDP has a reasonable maximum datagram size | ||
| 2 | receive accepts the prefix optional argument | ||
| 3 | send doesn't support multiple arguments anymore | ||
| 4 | send allows the selection of the substring to be sent | ||
| 1 | fix bug that caused select return tables not to be associative on windows | 5 | fix bug that caused select return tables not to be associative on windows |
| 2 | compiles with g++ | 6 | compiles with g++ |
| 3 | new sample unix domain support | 7 | new sample unix domain support |
| @@ -1,4 +1,7 @@ | |||
| 1 | 1 | ||
| 2 | fix manual for send and receive | ||
| 3 | add thanks to mike | ||
| 4 | |||
| 2 | change sock:send to use indices just like string.sub? | 5 | change sock:send to use indices just like string.sub? |
| 3 | use mike's "don't set to blocking before closing unless needed" patch? | 6 | use mike's "don't set to blocking before closing unless needed" patch? |
| 4 | take a look at DB's smtp patch | 7 | take a look at DB's smtp patch |
diff --git a/doc/introduction.html b/doc/introduction.html index 6468148..20c4d36 100644 --- a/doc/introduction.html +++ b/doc/introduction.html | |||
| @@ -113,7 +113,7 @@ The core LuaSocket is almost entirely implemented in C. It is | |||
| 113 | usually available as a dynamic library which the interpreter can load | 113 | usually available as a dynamic library which the interpreter can load |
| 114 | with the help of a loader module written in Lua. | 114 | with the help of a loader module written in Lua. |
| 115 | Beginning with version 2.0 and following the Lua 5.0 trend, all LuaSocket | 115 | Beginning with version 2.0 and following the Lua 5.0 trend, all LuaSocket |
| 116 | functionality is defined inside tables (or rather a namespaces). No global | 116 | functionality is defined inside tables (or rather namespaces). No global |
| 117 | variables are ever created. | 117 | variables are ever created. |
| 118 | Namespaces are obtained with the <tt>require</tt> Lua function, which loads | 118 | Namespaces are obtained with the <tt>require</tt> Lua function, which loads |
| 119 | and initializes any required library and returns the namespace. | 119 | and initializes any required library and returns the namespace. |
diff --git a/doc/tcp.html b/doc/tcp.html index 5f520e9..30e06f4 100644 --- a/doc/tcp.html +++ b/doc/tcp.html | |||
| @@ -260,7 +260,7 @@ method returns <b><tt>nil</tt></b> followed by an error message. | |||
| 260 | <!-- receive ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | 260 | <!-- receive ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> |
| 261 | 261 | ||
| 262 | <p class=name id=receive> | 262 | <p class=name id=receive> |
| 263 | client:<b>receive(</b>[pattern]<b>)</b> | 263 | client:<b>receive(</b>[pattern [, prefix]]<b>)</b> |
| 264 | </p> | 264 | </p> |
| 265 | 265 | ||
| 266 | <p class=description> | 266 | <p class=description> |
| @@ -283,6 +283,11 @@ the returned line. This is the default pattern; | |||
| 283 | of bytes from the socket. | 283 | of bytes from the socket. |
| 284 | </ul> | 284 | </ul> |
| 285 | 285 | ||
| 286 | <p class=parameters> | ||
| 287 | <tt>Prefix</tt> is an optional string to be concatenated to the beginning | ||
| 288 | of any received data before return. | ||
| 289 | </p> | ||
| 290 | |||
| 286 | <p class=return> | 291 | <p class=return> |
| 287 | If successful, the method returns the received pattern. In case of error, | 292 | If successful, the method returns the received pattern. In case of error, |
| 288 | the method returns <tt><b>nil</b></tt> followed by an error message which | 293 | the method returns <tt><b>nil</b></tt> followed by an error message which |
| @@ -305,18 +310,18 @@ too. | |||
| 305 | <!-- send +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | 310 | <!-- send +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> |
| 306 | 311 | ||
| 307 | <p class=name id=send> | 312 | <p class=name id=send> |
| 308 | client:<b>send(</b>string<sub>1</sub> [, | 313 | client:<b>send(</b>data [, i [, j]]<b>)</b> |
| 309 | string<sub>2</sub>, ... string<sub>N</sub>]<b>)</b> | ||
| 310 | </p> | 314 | </p> |
| 311 | 315 | ||
| 312 | <p class=description> | 316 | <p class=description> |
| 313 | Sends data through client object. | 317 | Sends <tt>data</tt> through client object. |
| 314 | </p> | 318 | </p> |
| 315 | 319 | ||
| 316 | <p class=parameters> | 320 | <p class=parameters> |
| 317 | All parameters should be strings. For small strings, it is always better to | 321 | <tt>Data</tt> is the string to be sent. The optional arguments |
| 318 | concatenate them in Lua (with the '<tt>..</tt>' operator) and pass the | 322 | <tt>i</tt> and <tt>j</tt> work exactly like the standard |
| 319 | result to LuaSocket instead of passing several independent strings. | 323 | <tt>string.sub</tt> Lua function to allow the selection of a |
| 324 | substring to be sent. | ||
| 320 | </p> | 325 | </p> |
| 321 | 326 | ||
| 322 | <p class=return> | 327 | <p class=return> |
| @@ -341,6 +346,22 @@ Alas, it wasn't returning <tt><b>nil</b></tt> in case of | |||
| 341 | error. So it was changed again in beta. | 346 | error. So it was changed again in beta. |
| 342 | </p> | 347 | </p> |
| 343 | 348 | ||
| 349 | <p class=note> | ||
| 350 | <b>Also important</b>: | ||
| 351 | In order to better support non-blocking I/O and to discourage | ||
| 352 | bad practice, the <tt>send</tt> method now only sends one string | ||
| 353 | per call. The other optional arguments allow the user to select | ||
| 354 | a substring to be sent in a much more efficient way than | ||
| 355 | using <tt>string.sub</tt>. | ||
| 356 | </p> | ||
| 357 | |||
| 358 | <p class=note> | ||
| 359 | Note: Output is <em>not</em> buffered. For small strings, | ||
| 360 | it is always better to concatenate them in Lua | ||
| 361 | (with the '<tt>..</tt>' operator) and send the result in one call | ||
| 362 | instead of calling the method several times. | ||
| 363 | </p> | ||
| 364 | |||
| 344 | <!-- setoption ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | 365 | <!-- setoption ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> |
| 345 | 366 | ||
| 346 | <p class=name id=setoption> | 367 | <p class=name id=setoption> |
diff --git a/src/buffer.c b/src/buffer.c index 33fae84..30be156 100644 --- a/src/buffer.c +++ b/src/buffer.c | |||
| @@ -64,23 +64,24 @@ int buf_meth_getstats(lua_State *L, p_buf buf) { | |||
| 64 | \*-------------------------------------------------------------------------*/ | 64 | \*-------------------------------------------------------------------------*/ |
| 65 | int buf_meth_send(lua_State *L, p_buf buf) { | 65 | int buf_meth_send(lua_State *L, p_buf buf) { |
| 66 | int top = lua_gettop(L); | 66 | int top = lua_gettop(L); |
| 67 | size_t total = 0; | ||
| 68 | int arg, err = IO_DONE; | ||
| 69 | p_tm tm = tm_markstart(buf->tm); | 67 | p_tm tm = tm_markstart(buf->tm); |
| 70 | for (arg = 2; arg <= top; arg++) { /* first arg is socket object */ | 68 | int err = IO_DONE; |
| 71 | size_t sent, count; | 69 | size_t size, sent; |
| 72 | const char *data = luaL_optlstring(L, arg, NULL, &count); | 70 | const char *data = luaL_checklstring(L, 2, &size); |
| 73 | if (!data || err != IO_DONE) break; | 71 | ssize_t start = (ssize_t) luaL_optnumber(L, 3, 1); |
| 74 | err = sendraw(buf, data, count, &sent); | 72 | ssize_t end = (ssize_t) luaL_optnumber(L, 4, -1); |
| 75 | total += sent; | 73 | if (start < 0) start = size+start+1; |
| 76 | } | 74 | if (end < 0) end = size+end+1; |
| 75 | if (start < 1) start = 1; | ||
| 76 | if (end > size) end = size; | ||
| 77 | if (start <= end) err = sendraw(buf, data+start-1, end-start+1, &sent); | ||
| 77 | /* check if there was an error */ | 78 | /* check if there was an error */ |
| 78 | if (err != IO_DONE) { | 79 | if (err != IO_DONE) { |
| 79 | lua_pushnil(L); | 80 | lua_pushnil(L); |
| 80 | lua_pushstring(L, buf->io->error(buf->io->ctx, err)); | 81 | lua_pushstring(L, buf->io->error(buf->io->ctx, err)); |
| 81 | lua_pushnumber(L, total); | 82 | lua_pushnumber(L, sent); |
| 82 | } else { | 83 | } else { |
| 83 | lua_pushnumber(L, total); | 84 | lua_pushnumber(L, sent); |
| 84 | lua_pushnil(L); | 85 | lua_pushnil(L); |
| 85 | lua_pushnil(L); | 86 | lua_pushnil(L); |
| 86 | } | 87 | } |
diff --git a/src/wsocket.c b/src/wsocket.c index d9da6fc..511dbdc 100644 --- a/src/wsocket.c +++ b/src/wsocket.c | |||
| @@ -373,12 +373,10 @@ static const char *wstrerror(int err) { | |||
| 373 | case WSANOTINITIALISED: | 373 | case WSANOTINITIALISED: |
| 374 | return "Successful WSAStartup not yet performed"; | 374 | return "Successful WSAStartup not yet performed"; |
| 375 | case WSAEDISCON: return "Graceful shutdown in progress"; | 375 | case WSAEDISCON: return "Graceful shutdown in progress"; |
| 376 | case WSATYPE_NOT_FOUND: return "Class type not found"; | ||
| 377 | case WSAHOST_NOT_FOUND: return "Host not found"; | 376 | case WSAHOST_NOT_FOUND: return "Host not found"; |
| 378 | case WSATRY_AGAIN: return "Nonauthoritative host not found"; | 377 | case WSATRY_AGAIN: return "Nonauthoritative host not found"; |
| 379 | case WSANO_RECOVERY: return "Nonrecoverable name lookup error"; | 378 | case WSANO_RECOVERY: return "Nonrecoverable name lookup error"; |
| 380 | case WSANO_DATA: return "Valid name, no data record of requested type"; | 379 | case WSANO_DATA: return "Valid name, no data record of requested type"; |
| 381 | case WSASYSCALLFAILURE: return "System call failure"; | ||
| 382 | default: return "Unknown error"; | 380 | default: return "Unknown error"; |
| 383 | } | 381 | } |
| 384 | } | 382 | } |
diff --git a/test/testclnt.lua b/test/testclnt.lua index f98a504..356350a 100644 --- a/test/testclnt.lua +++ b/test/testclnt.lua | |||
| @@ -25,7 +25,7 @@ function remote(...) | |||
| 25 | s = string.gsub(s, "\n", ";") | 25 | s = string.gsub(s, "\n", ";") |
| 26 | s = string.gsub(s, "%s+", " ") | 26 | s = string.gsub(s, "%s+", " ") |
| 27 | s = string.gsub(s, "^%s*", "") | 27 | s = string.gsub(s, "^%s*", "") |
| 28 | control:send(s, "\n") | 28 | control:send(s .. "\n") |
| 29 | control:receive() | 29 | control:receive() |
| 30 | end | 30 | end |
| 31 | 31 | ||
| @@ -120,7 +120,7 @@ function test_mixed(len) | |||
| 120 | local bp1, bp2, bp3, bp4 | 120 | local bp1, bp2, bp3, bp4 |
| 121 | remote (string.format("str = data:receive(%d)", | 121 | remote (string.format("str = data:receive(%d)", |
| 122 | string.len(p1)+string.len(p2)+string.len(p3)+string.len(p4))) | 122 | string.len(p1)+string.len(p2)+string.len(p3)+string.len(p4))) |
| 123 | sent, err = data:send(p1, p2, p3, p4) | 123 | sent, err = data:send(p1..p2..p3..p4) |
| 124 | if err then fail(err) end | 124 | if err then fail(err) end |
| 125 | remote "data:send(str); data:close()" | 125 | remote "data:send(str); data:close()" |
| 126 | bp1, err = data:receive() | 126 | bp1, err = data:receive() |
| @@ -144,9 +144,9 @@ function test_asciiline(len) | |||
| 144 | str10 = string.rep("aZb.c#dAe?", math.floor(len/10)) | 144 | str10 = string.rep("aZb.c#dAe?", math.floor(len/10)) |
| 145 | str = str .. str10 | 145 | str = str .. str10 |
| 146 | remote "str = data:receive()" | 146 | remote "str = data:receive()" |
| 147 | sent, err = data:send(str, "\n") | 147 | sent, err = data:send(str.."\n") |
| 148 | if err then fail(err) end | 148 | if err then fail(err) end |
| 149 | remote "data:send(str, '\\n')" | 149 | remote "data:send(str ..'\\n')" |
| 150 | back, err = data:receive() | 150 | back, err = data:receive() |
| 151 | if err then fail(err) end | 151 | if err then fail(err) end |
| 152 | if back == str then pass("lines match") | 152 | if back == str then pass("lines match") |
| @@ -162,9 +162,9 @@ function test_rawline(len) | |||
| 162 | math.floor(len/10)) | 162 | math.floor(len/10)) |
| 163 | str = str .. str10 | 163 | str = str .. str10 |
| 164 | remote "str = data:receive()" | 164 | remote "str = data:receive()" |
| 165 | sent, err = data:send(str, "\n") | 165 | sent, err = data:send(str.."\n") |
| 166 | if err then fail(err) end | 166 | if err then fail(err) end |
| 167 | remote "data:send(str, '\\n')" | 167 | remote "data:send(str..'\\n')" |
| 168 | back, err = data:receive() | 168 | back, err = data:receive() |
| 169 | if err then fail(err) end | 169 | if err then fail(err) end |
| 170 | if back == str then pass("lines match") | 170 | if back == str then pass("lines match") |
| @@ -457,7 +457,62 @@ function getstats_test() | |||
| 457 | print("ok") | 457 | print("ok") |
| 458 | end | 458 | end |
| 459 | 459 | ||
| 460 | |||
| 460 | ------------------------------------------------------------------------ | 461 | ------------------------------------------------------------------------ |
| 462 | function test_nonblocking(size) | ||
| 463 | reconnect() | ||
| 464 | remote(string.format([[ | ||
| 465 | data:send(string.rep("a", %d)) | ||
| 466 | socket.sleep(0.5) | ||
| 467 | data:send(string.rep("b", %d)) | ||
| 468 | ]], size, size)) | ||
| 469 | local err = "timeout" | ||
| 470 | local part = "" | ||
| 471 | local str | ||
| 472 | data:settimeout(0) | ||
| 473 | while 1 do | ||
| 474 | str, err, part = data:receive(2*size - string.len(part), part) | ||
| 475 | if err ~= "timeout" then break end | ||
| 476 | end | ||
| 477 | assert(str == (string.rep("a", size) .. string.rep("b", size))) | ||
| 478 | reconnect() | ||
| 479 | remote(string.format([[ | ||
| 480 | str = data:receive(%d) | ||
| 481 | socket.sleep(0.5) | ||
| 482 | str = data:receive(%d, str) | ||
| 483 | str = data:receive("*l", str) | ||
| 484 | data:send(str) | ||
| 485 | data:send("\n") | ||
| 486 | ]], size, size)) | ||
| 487 | data:settimeout(0) | ||
| 488 | local sofar = 1 | ||
| 489 | while 1 do | ||
| 490 | _, err, part = data:send(str, sofar) | ||
| 491 | if err ~= "timeout" then break end | ||
| 492 | sofar = sofar + part | ||
| 493 | end | ||
| 494 | data:send("\n") | ||
| 495 | data:settimeout(-1) | ||
| 496 | local back = data:receive() | ||
| 497 | assert(back == str) | ||
| 498 | print("ok") | ||
| 499 | end | ||
| 500 | |||
| 501 | |||
| 502 | ------------------------------------------------------------------------ | ||
| 503 | test("non-blocking transfer") | ||
| 504 | test_nonblocking(1) | ||
| 505 | test_nonblocking(17) | ||
| 506 | test_nonblocking(200) | ||
| 507 | test_nonblocking(4091) | ||
| 508 | test_nonblocking(80199) | ||
| 509 | test_nonblocking(8000000) | ||
| 510 | test_nonblocking(80199) | ||
| 511 | test_nonblocking(4091) | ||
| 512 | test_nonblocking(200) | ||
| 513 | test_nonblocking(17) | ||
| 514 | test_nonblocking(1) | ||
| 515 | |||
| 461 | test("method registration") | 516 | test("method registration") |
| 462 | test_methods(socket.tcp(), { | 517 | test_methods(socket.tcp(), { |
| 463 | "accept", | 518 | "accept", |
| @@ -548,7 +603,6 @@ test_mixed(1) | |||
| 548 | 603 | ||
| 549 | 604 | ||
| 550 | test("binary line") | 605 | test("binary line") |
| 551 | reconnect() | ||
| 552 | test_rawline(1) | 606 | test_rawline(1) |
| 553 | test_rawline(17) | 607 | test_rawline(17) |
| 554 | test_rawline(200) | 608 | test_rawline(200) |
| @@ -562,24 +616,6 @@ test_rawline(17) | |||
| 562 | test_rawline(1) | 616 | test_rawline(1) |
| 563 | 617 | ||
| 564 | test("raw transfer") | 618 | test("raw transfer") |
| 565 | reconnect() | ||
| 566 | test_raw(1) | ||
| 567 | test_raw(17) | ||
| 568 | test_raw(200) | ||
| 569 | test_raw(4091) | ||
| 570 | test_raw(80199) | ||
| 571 | test_raw(8000000) | ||
| 572 | test_raw(80199) | ||
| 573 | test_raw(4091) | ||
| 574 | test_raw(200) | ||
| 575 | test_raw(17) | ||
| 576 | test_raw(1) | ||
| 577 | |||
| 578 | test("non-blocking transfer") | ||
| 579 | reconnect() | ||
| 580 | -- the value is not important, we only want | ||
| 581 | -- to test non-blocking I/O anyways | ||
| 582 | data:settimeout(200) | ||
| 583 | test_raw(1) | 619 | test_raw(1) |
| 584 | test_raw(17) | 620 | test_raw(17) |
| 585 | test_raw(200) | 621 | test_raw(200) |
diff --git a/test/testsrvr.lua b/test/testsrvr.lua index 969f95b..23e3850 100644 --- a/test/testsrvr.lua +++ b/test/testsrvr.lua | |||
| @@ -1,29 +1,14 @@ | |||
| 1 | socket = require"socket" | 1 | socket = require("socket"); |
| 2 | 2 | host = host or "localhost"; | |
| 3 | host = host or "localhost" | 3 | port = port or "8080"; |
| 4 | port = port or "8080" | 4 | server = assert(socket.bind(host, port)); |
| 5 | 5 | ack = "\n"; | |
| 6 | server, error = socket.bind(host, port) | ||
| 7 | if not server then print("server: " .. tostring(error)) os.exit() end | ||
| 8 | ack = "\n" | ||
| 9 | while 1 do | 6 | while 1 do |
| 10 | print("server: waiting for client connection..."); | 7 | print("server: waiting for client connection..."); |
| 11 | control, error = server:accept() | 8 | control = assert(server:accept()); |
| 12 | assert(control, error) | ||
| 13 | -- control:setoption("nodelay", true) | ||
| 14 | while 1 do | 9 | while 1 do |
| 15 | command, error = control:receive() | 10 | command = assert(control:receive()); |
| 16 | if error then | 11 | assert(control:send(ack)); |
| 17 | control:close() | 12 | (loadstring(command))(); |
| 18 | print("server: closing connection...") | ||
| 19 | break | ||
| 20 | end | ||
| 21 | sent, error = control:send(ack) | ||
| 22 | if error then | ||
| 23 | control:close() | ||
| 24 | print("server: closing connection...") | ||
| 25 | break | ||
| 26 | end | ||
| 27 | (loadstring(command))() | ||
| 28 | end | 13 | end |
| 29 | end | 14 | end |
