New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add. acceptfd method. #48
Conversation
socket.tcp can accept fd and socket type ('master'(default), 'client')
acceptfd method can be used to write multi-threaded server.
```lua
-- main thread
local fd = srv_sock:acceptfd()
Threads.runfile('echo.lua', fd)
-- echo.lua
local fd = ...
local sock = socket.tcp(fd,'client')
```
or to interact with library such as [ESL](http://wiki.freeswitch.org/wiki/Event_Socket_Library)
```lua
local fd = srv_sock:acceptfd()
Threads.runfile('worker.lua', fd)
-- worker.lua
local sock = ESLconnection((...))
```
If we need just close fd (for example we can not run worker thread) we should call `socket.tcp(fd,'client'):close()`
|
Can this be solved with the "setfd/getfd" hack? |
|
We pass this |
|
acceptfd() is unnecessary, its easily replaced with :accept(), getfd(), setfd(-1) -- NOT 0, that will close your stdin. On the other side, to make a client tcp socket that uses that fd, not so possible. To replace the fd in a client socket, you first need a socket. So you need to create a connection to something. Then get its fd, close the fd (somehow outside of luasocket), then setfd() with the real underlying fd you want. I would really love to see socket.stream(), socket.dgram() methods that took fds, and a spec as to whether they are master (accept can be called) or client. Actually, even that could be avoided, accept() on a socket that isn't being listened on fails, anyhow, it can just be an error, so this abstract constructors could just expose all socket interfaces, but with the recv() being either buffer/pattern based, or packet/dgram based. This would allow applying the stream interface easily to, for example, serial and other char devices in unix. It would also better express that those are the abstractions, and help with the unfortunate unix socket case - the unix support only does unix stream sockets, not unix dgram. Anyhow, luasocket has the ONLY good stream interfaces in the lua world right now, they are really nice, and there will be increasing pressure to get access to them for use outside of luasocket. My serial.c (which is just an ugly copy of unix.c, because sharing the code would have involved a big refactor) is an example. If luasocket had a C API which allowed the construction of stream or dgram sockets, most of unix.c would disappear, and be shared with tcp.c. Same for serial.c. There could even be ONLY C APIs for creating sockets in this manner, so the fact that the APIs are non-portable wouldn't matter so much, only C modules built on top of luasocket would be using the non-portable interfaces, and C code already has ways of dealing with portability. I could then remove serial.c, and it would be a thin, 3rdparty, module that depends on luasocket. The lua lanes people could use the same hypothetical interface, they have lots of C code anyhow. Folks doing embedded systems, as well, could do the same. So, that's my proposal. Reject this pull request, and refactor tcp.c/unix.c so the common code can be used internally to luasocket, as well as by luasocket "add ons", then the add-on support becomes "somebody else's problem". |
|
If |
|
setfd(-1) works everywhere setfd() does.... i.e, not windows. I like socket.tcp(fd, 'client') OK. But I prefer a refactor of luasocket src internals so there is: socket.stream(fd), and socket.dgram(fd) which are 3 line bindings to an underlying API in luasocket, useable outside of luasocket: luasocket_stream_create(int sock, const char* classname); ... dgram_ () Course, that's a lot of refactoring, so not worth doing unless Diego likes the idea enough to be willing to pull it. |
|
I agree with everything Sam said with few reservations. LuaSocket was designed most of all to hide the many irritating platform specific idiosyncrasies from Lua users. I think we mostly did a good job at that. Most of the time somebody shows up claiming that there is something that they want to do but can't do with LuaSocket, we find a way. Then, of course, are the actual power users that want to do more system specific things. The question becomes: should we care? I usually try to weight the relevance of a particular proposal to the rest of the community. This is because, historically, it is I who end up having to maintain the code that some random person on the Internet wanted for their convenience. This is hard, as I don't have all these systems lying around, up to date, ready for testing. Also, I am a computer graphics researcher, and I can't invest as much time on this as when I was a grad student. :) IPv6 is obviously important. Let's try to make sure the support is complete enough the most people can use it without problems, in a portable way. It is hard for me to evaluate what is important and what is not, and this is why I am asking for your help. The streaming interface was designed to be extended to a certain degree. The original idea was to implement named pipes on Windows as well. And Unix domain sockets on, well, Unix. The demand simply never seemed to be there, and so we focused on other things. I like Sam's idea of factoring the streaming and dgram interfaces, and have different socket types be their clients (do we need seqpacket as well?). I am not sure about allowing the errors from undefined methods fall-through to the users. Let's brainstorm about this Sam. I want to make sure the underlying representation can be unified between Unix and Windows. At any rate, we should probably leave this for the next version? (BTW, utestsrvr/utestclnt are currently not running... :)). |
|
What if we define setfd method like: static int meth_setfd(lua_State *L)
{
p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
if(lua_gettop(L) == 1){
#ifdef _WIN32
tcp->sock = INVALID_SOCKET;
#else
tcp->sock = -1;
#endif
}
else tcp->sock = (t_socket) luaL_checknumber(L, 2);
return 0;
}and add ability create socket from -- main thread
local sock = srv_sock:accept()
if Threads.runfile('echo.lua', sock:getfd()) then sock:setfd() end
sock:close()
-- echo.lua
local fd = ...
local sock = socket.tcp(fd,'client') |
|
In meth_setfd(), no need for ifdef, use SOCKET_INVALID, defined in both usocket.h and wsocket.h |
On windows we can pass this
fdonly between threads.socket.tcpcan accept fd and socket type ('master'(default), 'client') and create newsocketobject.acceptfd method can be used to write multi-threaded server.
or to interact with library such as ESL
If we need just close fd (for example we can not run worker thread) we should call
socket.tcp(fd,'client'):close()