1. Post #1
    kna_rus's Avatar
    September 2008
    121 Posts
    Here it is - simple socket module with required minimum of functions, working in beta!
    This module is single-threaded, which means it's up to you to check sockets for incoming data. Example of that is shown below.
    Full support for binary strings included in Beta module.
    Supports both TCP and UDP.

    [release]
    Download:
    Non-Beta:
    Windows
    Linux
    Sources
    Beta:
    Windows
    Sources
    [/release]

    [release]FAQ:
    Q: This is single-threaded - it means it will block when I call recv()!
    A: You can set timeout to 0 and then call recv(). If there is no data, it will just return, instantly, without blocking.

    Q: Does this support sending/receiving of strings with nulls in them?
    A: Yes. This is new feature of Beta's Lua interface, and it all works pretty much as you would expect it to work.

    Q: How do I decode data from strings with nulls?
    A: If data format is fixed - use pattern matching. You can read about it at lua.org . Otherwise (I have no idea what it can be, if it is your own server-to-server communication - why not use strings without nulls?) - write your own binary reader in lua. Of course it will be slower that C++ binary reader, but I'm not sure if you need it.

    Q: Is there any way to use hostnames with this module?
    A: No, sorry. You might want to use another module to get IPs of hostnames, or just hardcode IPs.
    [/release]
    [release]
    Manual for Beta module:
    --Global functions:
    
    --creates a new socket
    --protocol is either IPPROTO_TCP or IPPROTO_UDP
    socket = Socket(protocol)
    
    --functions in socket metatable:
    
    --accept incoming connection
    --currently ignores timeout and may block
    --returns socket
    socket = s:Accept()
    
    --binds a socket to ip and port
    --ip may be "*" and port 0 to let the system to choose any free port
    s:Bind(ip,port)
    
    --closes socket
    --no more reading or writing should be done on closed sockets
    s:Close()
    
    --connects socket to ip/port
    --should be used only on tcp sockets
    --this DOES NOT resolve hostnames. You can connect only to IP.
    --ignores timeout, may block
    s:Connect(ip,port)
    
    --sets timeout for Recv functions
    --by default timeout is 0, it means do not wait for any data if there is no data
    s:SetTimeout(seconds)
    
    --send string to connected server
    --should be used only with tcp sockets
    --returns nil/false and error message or true
    success, error = s:Send(data)
    
    --send string to specified ip/port
    --returns nil/false and error message or true
    success, error = s:SendTo(data,ip,port)
    
    --receive data from connected peer
    --should be used only on TCP sockets
    --size is size of receive buffer, default is 8192 bytes
    --if an error occurs (including timeout), data is nil and err is error
    data, err = s:Recv([size])
    
    --receive data and return ip/port where it came from
    --recommended for UDP sockets
    --size is size of receive buffer, default is 8192 bytes
    --if an error occurs (including timeout), data is nil and ip is error
    data, ip, port = s:RecvFrom([size])
    

    All errors returned are strings describing error, i.e. "timeout" or "connection refused".
    [/release]

    [release]
    Examples:

    Source Server Query with callbacks, for Beta:
    --this code requires players on server to work
    --because it uses think
    local querystring = string.char(255):rep(4).."TSource Engine Query\0"
    local wait_table = {}
    local callback_table = {}
    
    hook.Add("Think","CheckReadySourceQueries",function()
        for k,v in pairs(wait_table) do
            local d, ip, port = v:RecvFrom()
            if d then
                local servername, map, game, gamemode, nump, maxp, dedi, os, pwd, secure, ver = d:match("\015(%Z+)%z(%Z+)%z(%Z+)%z(%Z+)%z..(.)(.).(.)(.)(.)(.)(%Z+)") --If you are wondering what is match and what are all these %Zs for, go read lua manual
                nump, maxp, pwd, secure = string.byte(nump), string.byte(maxp), string.byte(pwd), string.byte(secure)
                callback_table[v](ip,port,servername, map, game, gamemode, nump, maxp, dedi, os, pwd, secure, ver)
                v:Close()
                wait_table[k] = nil
                callback_table[v] = nil
            end
        end
    end)
    
    function QuerySourceServer(ip,port,callback)
        local nsc = Socket(IPPROTO_UDP)
        nsc:Bind("*",0)
        nsc:SendTo(querystring,ip,port)
        wait_table[nsc] = nsc
        callback_table[nsc] = callback
    end
    
    QuerySourceServer("88.191.102.162",27015,print)
    --output:
    --lua_openscript test.lua
    --Running script test.lua...
    --88.191.102.162 27015 Python1320 and CapsAdmin's Server gm_construct_flatgrass_v5 garrysmod QBox 12 15 d l 0 1 1.0.0.94
    [/release]
    Reply With Quote Edit / Delete Reply Russian Federation Show Events Dumb Dumb x 12Useful Useful x 6Lua King Lua King x 3Informative Informative x 1 (list)

  2. Post #2
    yakahughes's Avatar
    April 2008
    1,318 Posts
    After some my friends and me found out that OOSocket is not as awesome as it seems to be (crashes on linux, bugged threading, indirect control of socket), I decided to write my own luasocket-like module, that is not overloaded with any useless functions like threading, queueing and other stuff.
    It's annoying when people put down other people's work to make their own look better. Threading and queuing are not useless functions, and when you use OOSocks right you don't crash.
    Reply With Quote Edit / Delete Reply United States Show Events Agree Agree x 10Dumb Dumb x 2Disagree Disagree x 1 (list)

  3. Post #3
    Box collector
    haza55's Avatar
    October 2005
    545 Posts
    I have no problem with you writing this. Infact all you had to do was download the old OOSocks code before it was multi threaded.

    But I don't understand why you take no pride in your work. This entire thing looks like a copy paste job from other peoples work, shoved together and forced to work.

    Take some pride in your work, make something clear, styled and be professional.

    Edited:

    Reading your code, you are overwriting unallocated memory. You have logic errors.

    Your claiming it doesn't crash. This is only so because you have been lucky.
    Reply With Quote Edit / Delete Reply Australia Show Events Agree Agree x 6Friendly Friendly x 2Dumb Dumb x 1 (list)

  4. Post #4
    kna_rus's Avatar
    September 2008
    121 Posts
    Was OOSocks not multithreaded?
    Yes, around 25% of this is copypasted from Microsoft help or linux man pages. Basically all socket modules (non-threaded of course) consist of the same - select, recv, send, etc.

    Where exactly am I overwriting unallocated memory? Where do I have logic errors?
    And it does not crash. Recv is being called each frame, Send is called quite often (TCP), no crashes. Absolutely. Crashes may occur if you try to connect udp socket, but they never happen if you are using sockets as they are supposed to be used.
    Reply With Quote Edit / Delete Reply Russian Federation Show Events Dumb Dumb x 3 (list)

  5. Post #5
    yakahughes's Avatar
    April 2008
    1,318 Posts
    Here it is - simple socket module with required minimum of functions.
    I am no super good coder, but this works fine, fast and does not crash.
    Crashes may occur if you try to connect udp socket, but they never happen if you are using sockets as they are supposed to be used.
    So... it crashes if you use it wrong? Just like the useless, horrible OOSocks?
    Reply With Quote Edit / Delete Reply United States Show Events Agree Agree x 5Dumb Dumb x 2 (list)

  6. Post #6
    servak's Avatar
    July 2010
    44 Posts
    I can confirm that OOSocks was crashing on changelevel while active TCP connection, that module does not crash in same case.
    Reply With Quote Edit / Delete Reply Russian Federation Show Events Dumb Dumb x 3Useful Useful x 1 (list)

  7. Post #7
    kna_rus's Avatar
    September 2008
    121 Posts
    I didn't call OOSocks "useless" and "horrible", but in my opinion socket module does not need all the features OOSocks has. And it crashes randomly, not if I use it incorrectly.
    Reply With Quote Edit / Delete Reply Russian Federation Show Events Dumb Dumb x 1 (list)

  8. Post #8
    Cloudhunter's Avatar
    November 2007
    529 Posts
    So instead of reporting bugs you reinvented the wheel. Gg.

    Nice to know you're trying, but to call it bugged without at least attempting to get it fixed is stupid.
    Reply With Quote Edit / Delete Reply United Kingdom Show Events Agree Agree x 1 (list)

  9. Post #9
    kna_rus's Avatar
    September 2008
    121 Posts
    Yes, I reinvented the wheel. Simple round wheel. Without any unnecessary gyroscopes, breaking parts and sharp corners. I'm trying to keeps sockets simple, I don't need any threading and bugs randomly popping out of nowhere.
    Reply With Quote Edit / Delete Reply Russian Federation Show Events Dumb Dumb x 2Agree Agree x 2 (list)

  10. Post #10
    Cloudhunter's Avatar
    November 2007
    529 Posts
    Yes, I reinvented the wheel. Simple round wheel. Without any unnecessary gyroscopes, breaking parts and sharp corners. I'm trying to keeps sockets simple, I don't need any threading and bugs randomly popping out of nowhere.
    Fair enough that you wrote something that works for you, however if you had bugs you should have reported them. How would you feel if people discovered bugs in yours, and rather than reported them just went and made their own saying yours was shit? That's effectively what you are saying, and your attitude is appalling.

    Glad this works for you, but just because something is more complicated doesn't mean it has to be buggy by its very definition as you seem to imply. Simple things have just as much opportunity to be buggy.

    Edited:

    You also say the OOSocks has useless functions. Useless for you, yes. Not for other people.
    Reply With Quote Edit / Delete Reply United Kingdom Show Events Agree Agree x 1 (list)

  11. Post #11
    kna_rus's Avatar
    September 2008
    121 Posts
    I reported bugs. I posted code and dumps that crashed server. This bug got fixed just now.
    Reply With Quote Edit / Delete Reply Russian Federation Show Events Dumb Dumb x 2Agree Agree x 2 (list)

  12. Post #12
    likes men
    Python1320's Avatar
    May 2007
    1,717 Posts
    GM13 please?

    This may be the least advanced socket module but definitely quickest/easiest to port.

    EDIT: Thanks :)

  13. Post #13
    kna_rus's Avatar
    September 2008
    121 Posts
    I've updated this module for Beta.
    RecvTable functions are now gone, since Beta supports proper string handling, and Send functions don't use length argument anymore. Also, I've removed GetHostByName since it didn't work anyway, and there are better DNS modules out there.
    Feel free to use. And report bugs, I haven't done much testing for Beta, but I can tell for sure that TCP part works fine.
    Reply With Quote Edit / Delete Reply Windows 7 Russian Federation Show Events Friendly Friendly x 2Dumb Dumb x 1Funny Funny x 1 (list)

  14. Post #14
    Nebual's Avatar
    June 2009
    102 Posts
    'require("litesocket")' alone seems to crash me, running latest Gmod Beta (Sept 21st, Beta Update 34). Tried on a fresh install, with gmsv_litesocket.dll in lua/bin/. Is there some new way to load modules?

    Thanks for updating!

  15. Post #15
    kna_rus's Avatar
    September 2008
    121 Posts
    Apparently I've missed one of Garry's interface updates, so it really crashed. I updated it, now works fine on my dedicated server. Here is the link (it's the same, just redownload) https://dl.dropbox.com/u/3679614/gmsv_litesocket.dll
    Reply With Quote Edit / Delete Reply Windows 7 Russian Federation Show Events Useful Useful x 1 (list)

  16. Post #16
    Nebual's Avatar
    June 2009
    102 Posts
    Awesome, thanks! Works great for my IRC integration plugin!

    Not really a big deal, since its solveable in lua by hooking into Shutdown, but your module does not auto disconnect sockets. If it were possible to pickup the socket reference after a map change, it'd probably be useful for some people to have it not auto disconnect, but otherwise sockets should probably close with lua.

  17. Post #17
    Nebual's Avatar
    June 2009
    102 Posts
    Beta V39 changed binary module headers again (probably as part of the luajit addition), so this isn't loading again.

    Thanks for maintaining this!

  18. Post #18
    kna_rus's Avatar
    September 2008
    121 Posts
    I've updated module for latest GMod Beta with LuaJIT.
    As for sockets closing on shutdown, it's broken at the moment. You should close them manually in Shutdown hook.

  19. Post #19
    likes men
    Python1320's Avatar
    May 2007
    1,717 Posts
    Could you make the sockets truly non blocking?
    Code:
    		int flags = fcntl(sc, F_GETFL, 0);
    		fcntl(sc, F_SETFL, flags | O_NONBLOCK);
    Otherwise I can't use tcp :Accept() since it would block.


    Also could we have the accepted ip/port returned also on the :Accept function?

  20. Post #20

    July 2012
    66 Posts
    hey there, could you explane me how to use the udp ?
    somehow it wont work for me, even if i just want to receive one line of data,..

    thats the testing snippet:
    Code:
    require('litesocket')
    
    socket = Socket(IPPROTO_UDP)
    ip = "localhost"
    port = 7777
    socket:Accept()
    socket:SetTimeout(0)
    socket:Bind(ip, port)
    
    data, ip, port = socket:RecvFrom()
    
    print(data)
    print(socket)
    prints:
    Code:
    nil
    socket{udp,unbound}
    R
    now if i dont bind the port i need with socket:Bind("*", 0)
    thats printed out:
    Code:
    nil
    socket{udp,bound}

    i really need a working udp lib, thanks in advance for answers!

    numu

  21. Post #21
    likes men
    Python1320's Avatar
    May 2007
    1,717 Posts
    Don't forget to socket:Listen(1234)

  22. Post #22

    July 2012
    66 Posts
    thanks for the answer!
    but could you give me an example ?

    where does the listen statement need to go? what is the parameter in the listenfunction?

    i already fail to bind the ip / port, it just wont let me, just if i keep it open it does let me bind,... : (

    i know i am a real newbie, but again i have to say its so hard to get into this whole structure without a good documentation, and listen is not listed in the docu from kna_rus ..

    thanks in advance
    numu

    Edit: Anyway my ip is always timedout, any way i try it.. binding this binding that,.. setting the variables ip/port, not setting the variables ip/port.. and so on..

  23. Post #23
    Nebual's Avatar
    June 2009
    102 Posts
    Could you perhaps post a Linux binary? Thanks!

  24. Post #24
    Trinexx's Avatar
    August 2008
    9 Posts
    I'd like to see a linux binary myself.

  25. Post #25
    likes men
    Python1320's Avatar
    May 2007
    1,717 Posts
    What about full blown luasocket? (linux only) http://g.iriz.uk.to/~srcds/modules/gm13/bin/
    You need to edit srcds_run and find LD_LIBRARY_PATH and add garrysmod/bin to it though.
    Reply With Quote Edit / Delete Reply Windows 7 Finland Show Events Informative Informative x 1 (list)

  26. Post #26

    July 2012
    66 Posts
    -snip-

  27. Post #27

    July 2012
    66 Posts
    it seems like the library stoped working after one of the last patches : (

    would be great if you could have a look on it!

    cheers!
    numu

    edit:
    i guess it has to do with the timer.object
    Reply With Quote Edit / Delete Reply Windows 7 Austria Show Events Late Late x 1 (list)