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:

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') )  

This is working fine. But, coming from AS3, with its listener paradigm, I’m totally confused as to how to receive messages back from the server. I try the “receive” method on the client object, but then corona just hangs. How can I create a function that will accept incoming strings from the socket?

Thanks,
Mike [import]uid: 4454 topic_id: 2877 reply_id: 302877[/import]

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 [import]uid: 4454 topic_id: 2877 reply_id: 8457[/import]

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.

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)  

Outputs:

nil timeout <?xml version="1.0" encoding="utf-16"?><message source="Me" class="First" subclass="Human">Hello</message>  

I believe these three results are: data, error, and latest client message.
[import]uid: 4454 topic_id: 2877 reply_id: 8463[/import]

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? [import]uid: 8541 topic_id: 2877 reply_id: 8497[/import]

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

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 ). [import]uid: 4454 topic_id: 2877 reply_id: 8498[/import]

Is a non blocking implementation planned ?

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

Like chat, multiplayer games,… [import]uid: 4426 topic_id: 2877 reply_id: 8608[/import]

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… [import]uid: 4454 topic_id: 2877 reply_id: 8652[/import]

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 [import]uid: 4426 topic_id: 2877 reply_id: 8675[/import]

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. :slight_smile: [import]uid: 4454 topic_id: 2877 reply_id: 8758[/import]

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.
[import]uid: 295 topic_id: 2877 reply_id: 8804[/import]

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 :slight_smile:

  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 :slight_smile:

  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 :slight_smile:
    [import]uid: 4426 topic_id: 2877 reply_id: 8831[/import]

socat works well for me on the server side

http://www.dest-unreach.org/socat/doc/socat.html [import]uid: 10016 topic_id: 2877 reply_id: 8852[/import]

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. [import]uid: 4426 topic_id: 2877 reply_id: 8856[/import]

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. [import]uid: 10016 topic_id: 2877 reply_id: 8951[/import]

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 [import]uid: 4426 topic_id: 2877 reply_id: 8972[/import]

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 [import]uid: 5354 topic_id: 2877 reply_id: 9848[/import]

I second that. It would be great to have access to a Lua module for detecting network availability and such. [import]uid: 1560 topic_id: 2877 reply_id: 9853[/import]

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 [import]uid: 5354 topic_id: 2877 reply_id: 9900[/import]

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 ?
[import]uid: 9079 topic_id: 2877 reply_id: 10268[/import]

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 [import]uid: 5354 topic_id: 2877 reply_id: 10269[/import]