Incoming Socket TCP Communication

Hello,

I'm connecting to a socket server, and am trying to inspect responses. I am already able to send messages:

1
2
3
4
5
connectObject.socket = require( "socket" )
connectObject.client = connectObject.socket.tcp()
connectObject.isClient = connectObject.client:connect( "192.168.1.73" , 1027 )
 
connectObject.client:send(  '<h >hey</h>\0') )

I think I'd like to rephrase my question as:

What's the simplest way to use a socket to connect to a peer, or remote socket, and send/receive data in real time? Data, meaning small XML messages.

Mike

Ok, figured it out, at the most basic level. Set the timeout of the client to 0 (anything else freezes playback), and run a timer to listen for received messages. If anyone sees this as a bad approach, please let me know.

1
2
3
4
5
6
7
8
9
10
11
connectObject.socket = require( "socket" )
connectObject.client = connectObject.socket.tcp()
connectObject.client:connect( "localhost" , 1025 )
connectObject.client:settimeout( 0 )
 
timer.performWithDelay( 200, function() 
 
        connectObject.client:send( '<?xml version="1.0" encoding="utf-16"?><Message source="Me" class="First" subclass="Human">Hello</Message>\0' ) 
        print( connectObject.client:receive('*l'))
 
end, 0)

This is currently one of the negatives of Corona, it does not support the connection method you want. Mainly, you want to send a packet, and setup a listener that will fire an event when Corona detects packets returning, all while your application is still running.

Currently, socket calls like this will stop execution of your application... and wait.. and wait.. until data is returned, or timeout happens.

Your last example of code is, I believe, misleading you in to thinking this is working properly, but I am not quite so sure. The LUA docs on send and receive:

http://w3.impa.br/~diego/software/luasocket/tcp.html

Which has this blurb about what returns from :receive

"In case of error, the method returns nil followed by an 
error message which can be the string 'closed' in case the 
connection was closed before the transmission was completed 
or the string 'timeout' in case there was a timeout during 
the operation. Also, after the error message, the function 
returns the partial result of the transmission."

Since your timeout is now 0, that receive function is actually returning an error. However, I admit I dont see how it is getting the string that you sent, unless that string is actually just repeating what was sent.

Can you try and send something to google.com and port 80 instead of localhost?

Yeah, I've seen the program halt on receive. Not the desired effect I need. :)

I tried the google.com thing, and received nil, timeout, but no "partial result of the transmission".

However, I did more tests. I connect this app to an socket server running in Air. I also connect another client app (again, made with Air) to that server, which sends similar messages in XML. The idea is to have the two apps talking to each other through that socket server.

The third return from the receive method is actually the message from the client Air app, as well as whatever the Corona app sends. So, this code actually is doing what I need. All I need to do is inspect the source attribute in the XML to tell if I need to act upon it. This is performing, at the moment, just like I'd expect in a Flash app. Also, the animation is still running smooth ( and I'm doing some pretty complicated motion math ).

Is a non blocking implementation planned ?

This is needed for about every possible use case I can imagine.

Like chat, multiplayer games,....

EducasSoft,

Actually, looking at this page in Programming for Lua, we can see that this method IS a non-blocking implementation (look down a bit at the second receive function). I'll just need to refine it some more...

Page 83 of Programming for Lua

I'm currently writing my own module for realtime socket communication. It's looking promising...

Hi is there anything you could share on this?

On the google page I found the word coroutine and I didn't know that Lua supported coroutines. Maybe that is the trick you are using?

My purpose is to make corona connect to a simple socket server which is on my server and listening for connections to port 2222. Is can accept a huge number of connections which can then send strings of info to the server.

I'd be so happy if this would be possible from a corona program by using a socket.

Kind regards,

Bart

So far from my tests, with my previous code from above, and the explanation from the page in that book, I seem to understand it as this:

The timeout is set to 0. And on every tick from that timer, as I call the client:receive('*l") method, the partial results are whatever the socket has received up to that moment. So far, every small xml message that gets sent to the socket server, whether it be from the corona app, or a second app, gets sent to that buffer. This discovery opens possibilities. The "checker" could listen for terminating strings, even if the message is only partial, and combine current results to the last.

I've gotten every message in its entirety, so far. I don't know how it'd handle multiple simultaneous messages. I'm going to be doing further work on that, as well as learn about the coroutine method. I've searched this site, and I don't think I've read anything that says Corona can't do them... I just don't think anyone's tried. :)

EducaSoft

Could you pleas describe the "socket server" that's running on your server: 1. how you created it? 2. What language it's programed in? 3. Your server OS? 4. How you installed it on your server?

The reason I ask is I want to be able to do the same thing in the near future.

Hehe, I saw that question coming.
Its not that easy to make a good working socket server, isn't it?

Well to explain it

1) Its created to be a multithreaded socket server accepting connections (at this moment 1000 but by setting a global var I can easily just accept 10000 too). It accepts text strings for commands and can give (at this moment) a user a nickname, users can join 1 gameroom and the system is able to send private messages to 1 person or room messages to every person in the same room. This is of course the base functionality, because the rest is then built on top of that server to give gameplay functionality. So the game logic is programmed into the server so users can also not cheat. The reason why its so difficult to build something like that is because you want to use as little memory as possible and you want to be able to handle as many possible connections. So it must be 100% foolproof with no memory leaks. At the time of this writing the system handles about 1000 connections in below 120MB ram. Since every thread by default seems to take about 100kb, I find that very reasonable. Also, 1000 connected users is allready a nice number. If you have that number of users connected simultaneously, then I think you easily can afford a server with more then 120MB of free ram :-)

2) Its written in JAVA, so you can actually run it about everywhere (although I would strongly encourage to use a linux environment, because when we stresstested the server on windows, windows goes berzerk after opening aproximately 15000 socket connections, while linux easily goes way higher without any memory problems. At this moment our server runs on fedora 12, but it can run everywhere java can run (No I won't try to compile it on android :-)

3) Server OS here fedora 12

4) How to install? You just make sure you have shell access to the server, then upload a couple of java .class files (minimum 2) to a directory on the server and then you type "java socketServer" and it runs :-)

socat works well for me on the server side

http://www.dest-unreach.org/socat/doc/socat.html

Do I read well that socat handles 2 bidirectinal connections ?

What I was talking about was 1000 or maybe 20000 connections, totally threadsafe and with added artificial intelligence on serverside.

Maybe I read socat docs wrong or I didn't read enough of it, but this seems like a totally other kind of program.

socat can fork for each connection and it can be used bi or uni directional. I believe it is threadsafe but I say that based on a minimal search and with me not being an expert.

From my experience I would say that a medium box or instance devoted to the task could handle 1000 connections but 20,000 makes me think of a lot of possible limits that would have to be adjusted.

I am only doing a few connections. It's very fast, flexible and un-bloated, like lua socket itself.

But did anybody now get the sockets working in corona?

I mean, can we make a connection to for example IP 100.101.102.103 on port 1234 , send a string of info on connection and then send data and poll for info like in a chat application ?

I would die to get a solution for this. My multiplayerserver is online, but it looks like there is no onDataAvailable event or something similar on which we could react.

Please if somebody can help it would be so much appreciated.

Kind regards,

Bart

Hi Mike

I tried running the code and its throwing back errors.

Did you manage to get this working without freezing the app.

I basically need to send info between 2 iPhone on a local network and im hitting a wall. Sockets are not my thing!

Matt

I second that. It would be great to have access to a Lua module for detecting network availability and such.

its been a painful couple of hours but ive learned about coroutine and I now have a tcp listener that will listen for, accept and process a connection.

not sure I like the way the coroutine needs to be resumed on a frame by frame basis though, seems like it should be able to just run as a separate thread

Hello,

I am faced with the same need, and have not found any solution yet to have asynchronous sockets, even with coroutines... Still working on it. (if anybody has found the solution, he's welcome ! )

The better would be to have callback functions on receive events, for example.

By looking for information, I've found the following library, which sounds relevant :
http://keplerproject.github.com/copas/

May be it could be interesting to have it included into corona ?

I tried copas but I noticed it crashes Corona after a while and I couldn't figure out why. So I gave up on that.

For TCP I have a listener working that doesnt hold up the loop and will receive data if any is sent and pass that to a function.

The next step would be to write a TCP server to send data, along the same principles. Then get the 2 talking.

Looking at it, it doesnt seem overly hard to implement. Especially if I ignore any errors generated and just process successful TCP connections.

Once I have something working I will post my results

I may have a solution... but can not say yet if it will allow thousands of clients...
Nevertheless, it works, by making the following :

- installed PHP socketServer (http://blog.ixti.ru/archives/116)

- no coroutine, juste EnterFrame event with 0 timeout :

1
2
3
4
5
6
7
8
9
10
11
12
local function onEnterFrame(event)
        local txt = stcp:receive("*l")
        if txt then 
                print("RECEIVED : "..txt)
        end
end
 
stcp = socket.tcp()
stcp:connect("socketserver IP","socketserver port")
stcp:settimeout(0)
 
Runtime:addEventListener( "enterFrame", onEnterFrame )

Does that lose the connection after the first tcp packet is received?

I need to look at my code but I think the corouting is to enable you to keep the connection open

The connection is kept opened after. It listens untill the socket is closed.

I understood that coroutines are just used to allow a 'kind of' multithreading. That's all. They can be used with sockets to allow to listen to socket without hanging main process, that's all.

Here, the enterFrame event is used the same way.

Even the coroutine will hang the whole app while the TCP waits, the timeout is the same, so the code is similar to yours.

The coroutine enables you, on the next frame, to resume the routine. Thats all really but in my research on coroutines and TCP (much like copas) there is some reason for using it.

I will need to look a my code, its at home, but im sure there is a valid reason. Maybe its more for the master rather than the client TCP code

My own solution is similar to Olivier's at msg #20. My app is using a client connection, and runs a timer loop, except I use the "partial results" from the buffer. In my tests, it seems most messages are received, event using "*a" in the receive.

Since this is a prototype app, I'm not too concerned with precision. Also, this method is non-blocking, so the animation still plays uninterrupted.

I still wish there were more examples of a client connection sending and receiving short messages, at least to validate that what I'm doing is the right way.

Here's a demo of what I accomplished with LuaSocket: There os a game client running in the Corona Simulator and there is the game server, which is actually the game AI, running in a terminal window on the Mac. The game server is in pure Lua.

http://www.youtube.com/watch?v=xqeSdHKp_aw

views:4364 update:2011/9/26 8:07:09
corona forums © 2003-2011