TCP Server - how to continuously send data?

Hi,

I’ve been trying to get Corona to talk to my Processing sketch with sucesss thanks to the code Matthew Pringle made available (below). however, I’m unsure how to send realtime messages.
How would I proceed to have Corona send new messages say when a button is pressed?

Thanks!

local socket = require("socket");  
   
local tcpServer;  
   
local function createTCPServer( port )  
 -- Create Socket  
 local tcpServerSocket, err = socket.tcp();  
 local backlog = 5; -- Max number of accepted connections to server  
   
 -- Check Socket  
 if tcpServerSocket == nil then   
 return nil, err;  
 end  
   
 -- Allow Address Reuse  
 tcpServerSocket:setoption( "reuseaddr" , true );  
   
 -- Bind Socket  
 local res, err = tcpServerSocket:bind( "\*" , port );  
 if res == nil then  
 return nil, err;  
 end  
   
 -- Check Connection  
 res, err = tcpServerSocket:listen( backlog );  
 if res == nil then   
 return nil , err;  
 end  
   
 -- Return Server  
 return tcpServerSocket;  
end  
   
local function runTCPServer()  
 local tcpClient, tcpClientMessage;  
 local completeMessage = "";  
  
 -- Set Timeout  
 tcpServer:settimeout(0); -- Additional delay between each socket listen event.  
   
 -- Set Client  
 tcpClient, \_ = tcpServer:accept();  
   
 -- Get Message  
 if tcpClient then  
 -- The max allowed time between messages is 10ms, after which the sender is  
 -- considered to have finished sending data.  
 tcpClient:settimeout(.01);  
  
 while true do  
 tcpClientMessage, \_ = tcpClient:receive();  
  
 if tcpClientMessage == nil then  
 break;  
 end  
   
 --print("Message: " .. tcpClientMessage);  
 completeMessage = completeMessage .. "\n" .. tcpClientMessage;  
 end  
   
 -- Get rid of the first char ('\n') which was manually inserted.  
 completeMessage = completeMessage:sub(2);  
  
 tcpClient:send(20);  
 tcpClient:close();  
 else  
 -- Error  
 end  
end  
   
  
  
   
-- Make sure to enable port forwarding for port 8080 on your router, and enable   
-- inbound + outbound for port 8080 on your Windows/Mac firewall.  
tcpServer , \_ = createTCPServer("8080");  
Runtime:addEventListener( "enterFrame" , runTCPServer);  
-- tcpServer.close() is done on program exit. Call the close method manually  
-- if you're turning off server.  
  

Alex [import]uid: 66618 topic_id: 19728 reply_id: 319728[/import]

You should call socket:send(…) function to send data over socket connection. Please check tutorials coming with corona sdk if you do not know how to do basic things such as handling tap events.

deniz. [import]uid: 11686 topic_id: 19728 reply_id: 76360[/import]

Hi Deniz,

Thanks for your reply however socket:send() is giving me a runtime error.
Here is what I’ve been trying:
I commented out a bunch of other failed "guesses:

[code]local socket = require(“socket”);

local tcpServer;

local function createTCPServer( port )
– Create Socket
local tcpServerSocket, err = socket.tcp();
local backlog = 5; – Max number of accepted connections to server

– Check Socket
if tcpServerSocket == nil then
return nil, err;
end

– Allow Address Reuse
tcpServerSocket:setoption( “reuseaddr” , true );

– Bind Socket
local res, err = tcpServerSocket:bind( “*” , port );
if res == nil then
return nil, err;
end

– Check Connection
res, err = tcpServerSocket:listen( backlog );
if res == nil then
return nil , err;
end

– Return Server
return tcpServerSocket;
end

local function runTCPServer()
local tcpClient, tcpClientMessage;
local completeMessage = “”;

– Set Timeout
tcpServer:settimeout(0); – Additional delay between each socket listen event.

– Set Client
tcpClient, _ = tcpServer:accept();

– Get Message
if tcpClient then
– The max allowed time between messages is 10ms, after which the sender is
– considered to have finished sending data.
tcpClient:settimeout(.01);

while true do
tcpClientMessage, _ = tcpClient:receive();

if tcpClientMessage == nil then
break;
end

–print("Message: " … tcpClientMessage);
completeMessage = completeMessage … “\n” … tcpClientMessage;
end

– Get rid of the first char (’\n’) which was manually inserted.
completeMessage = completeMessage:sub(2);

tcpClient:send(“test”);
tcpClient:close();
else
– Error
end
end

– Make sure to enable port forwarding for port 8080 on your router, and enable
– inbound + outbound for port 8080 on your Windows/Mac firewall.
tcpServer , _ = createTCPServer(“8080”);
Runtime:addEventListener( “enterFrame” , runTCPServer);
– tcpServer.close() is done on program exit. Call the close method manually
– if you’re turning off server.

local function sendNow (event)

–tcpClient:send(“yahoo!”)
Socket:send(“yahoo!”)
–tcpServerSocket:send(“yahoo!”)
–ServerSocket:send(“yahoo!”)
–tcpServer:send(“yahoo!”)

– RUNTIME ERROR Terminal says
–?: in function <?:514>,
–?: in function <?:215>
end

sendTimer = timer.performWithDelay(1000,sendNow,0)

[/code]

I’m not too bothered about getting corona to read anything as I only need to blindly spit data out so if there is a way to simplify the above code to a straight forward outgoing server, that would be nice…

I’m kind of guessing at this point but I’m sure it’s something obvious… please help!
Thanks!!! [import]uid: 66618 topic_id: 19728 reply_id: 76376[/import]

Hi,

If you only want to connect to a remote service and send data, just use the code below;

local socketlib = require("socket")  
local socket = socketlib.tcp();   
  
local status,err = socket:connect( service\_host, service\_port )  
if status == nil then  
 print(err)  
end   
  
socket:send("data to send")  
socket:close()  
  

Remember to set service_host, and service_port properly. Also if you want to read data, you can always setup a timer and issue socket:read(). But dont forget to set timeout to 0 or your application will become unresponsive.

socket:settimeout(0)   

[import]uid: 11686 topic_id: 19728 reply_id: 76377[/import]

Hi Deniz,

Thanks for the code. No errors but now the Processing sketch can’t connect to corona:

java.net.ConnectException: Connection refused
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:432)
at java.net.Socket.connect(Socket.java:529)
at java.net.Socket.connect(Socket.java:478)
at java.net.Socket.(Socket.java:375)
at java.net.Socket.(Socket.java:189)
at processing.net.Client.(Client.java:75)
at Wirless_midi.setup(Wirless_midi.java:29)
at processing.core.PApplet.handleDraw(PApplet.java:1608)
at processing.core.PApplet.run(PApplet.java:1530)
at java.lang.Thread.run(Thread.java:680)

I’m using the same port and ip as the previous code. What has changed which could cause the server to become invisible to Processing?
Thanks for your help

[import]uid: 66618 topic_id: 19728 reply_id: 76379[/import]

ah my bad! you try to run a server on your device, hence tcpserver, and wish processing application to connect and send/receive data…

forget my sample code. its conneting to a remote service ie remote server. If you would like to accept connections you should definetly use Mathews code.

As I do not know what your processing server sends out, I can not give further advices. Matthew’s code reads delimited lines from server and then closes connection. This implementation is not what you want probably, as you want to send out data.

You may try this; dont close server socket. ie ommit below;

tcpClient:send(20);  
tcpClient:close();  

If you want to send data use this; (in a button tap handler)

tcpClient:send("data to send")  

ofcourse you should define tcpClient at the top of your definitions, not just in runTCPServer() function.

hope it helps.

[import]uid: 11686 topic_id: 19728 reply_id: 76380[/import]

Thanks Deniz, I appreciate your support

I omitted tcpClient:close(); and defined tcpClient at the top of the code.

Am I defining tcpClient properly? Here is my latest code:

  
local socket = require("socket");  
   
local tcpServer;  
  
local tcpClient  
  
local function createTCPServer( port )  
 -- Create Socket  
 local tcpServerSocket, err = socket.tcp();  
 local backlog = 5; -- Max number of accepted connections to server  
   
 -- Check Socket  
 if tcpServerSocket == nil then   
 return nil, err;  
 end  
   
 -- Allow Address Reuse  
 tcpServerSocket:setoption( "reuseaddr" , true );  
   
 -- Bind Socket  
 local res, err = tcpServerSocket:bind( "\*" , port );  
 if res == nil then  
 return nil, err;  
 end  
   
 -- Check Connection  
 res, err = tcpServerSocket:listen( backlog );  
 if res == nil then   
 return nil , err;  
 end  
   
 -- Return Server  
 return tcpServerSocket;  
end  
   
local function runTCPServer()  
 local tcpClient, tcpClientMessage;  
 local completeMessage = "";  
  
 -- Set Timeout  
 tcpServer:settimeout(0); -- Additional delay between each socket listen event.  
   
 -- Set Client  
 tcpClient, \_ = tcpServer:accept();  
   
 -- Get Message  
 if tcpClient then  
 -- The max allowed time between messages is 10ms, after which the sender is  
 -- considered to have finished sending data.  
 tcpClient:settimeout(.01);  
  
 while true do  
 tcpClientMessage, \_ = tcpClient:receive();  
  
 if tcpClientMessage == nil then  
 break;  
 end  
   
 --print("Message: " .. tcpClientMessage);  
 completeMessage = completeMessage .. "\n" .. tcpClientMessage;  
 end  
   
 -- Get rid of the first char ('\n') which was manually inserted.  
 completeMessage = completeMessage:sub(2);  
  
 --tcpClient:send("test");  
 --tcpClient:close();  
 else  
 -- Error  
 end  
end  
   
   
  
-- Make sure to enable port forwarding for port 8080 on your router, and enable   
-- inbound + outbound for port 8080 on your Windows/Mac firewall.  
tcpServer , \_ = createTCPServer("8080");  
Runtime:addEventListener( "enterFrame" , runTCPServer);  
-- tcpServer.close() is done on program exit. Call the close method manually  
-- if you're turning off server.  
  
 local function sendNow (event)  
  
tcpClient:send("test")  
  
 end  
   
sendTimer = timer.performWithDelay(1000,sendNow,-1)  
  

Still the same runtime error… Any thoughts?

Thanks!! [import]uid: 66618 topic_id: 19728 reply_id: 76382[/import]

You should remove tcpClient definition from runTCPServer() function… It is already defined at the top. [import]uid: 11686 topic_id: 19728 reply_id: 76393[/import]

Thanks!
I look forward to trying it when I get back from work.
Can’t wait to get this working-hoping to get a touchosc equivalent protocol going :slight_smile: [import]uid: 66618 topic_id: 19728 reply_id: 76405[/import]

Hi again,
I made the changes you suggested but still get this runtime error:

Runtime error /Users/alkex/Documents/Iphone Apps/tcp test/main.lua:84: attempt to index upvalue 'tcpClient' (a nil value) stack traceback: [C]: ? /Users/alkex/Documents/Iphone Apps/tcp test/main.lua:84: in function '\_listener' ?: in function <?:514> ?: in function <?:215>
Here is my current code:

[code]local socket = require(“socket”);

local tcpServer;

local tcpClient

local function createTCPServer( port )
– Create Socket
local tcpServerSocket, err = socket.tcp();
local backlog = 5; – Max number of accepted connections to server

– Check Socket
if tcpServerSocket == nil then
return nil, err;
end

– Allow Address Reuse
tcpServerSocket:setoption( “reuseaddr” , true );

– Bind Socket
local res, err = tcpServerSocket:bind( “*” , port );
if res == nil then
return nil, err;
end

– Check Connection
res, err = tcpServerSocket:listen( backlog );
if res == nil then
return nil , err;
end

– Return Server
return tcpServerSocket;
end

local function runTCPServer()
local tcpClientMessage;
local completeMessage = “”;

– Set Timeout
tcpServer:settimeout(0); – Additional delay between each socket listen event.

– Set Client
tcpClient, _ = tcpServer:accept();

– Get Message
if tcpClient then
– The max allowed time between messages is 10ms, after which the sender is
– considered to have finished sending data.
tcpClient:settimeout(.01);

while true do
tcpClientMessage, _ = tcpClient:receive();

if tcpClientMessage == nil then
break;
end

–print("Message: " … tcpClientMessage);
completeMessage = completeMessage … “\n” … tcpClientMessage;
end

– Get rid of the first char (’\n’) which was manually inserted.
completeMessage = completeMessage:sub(2);

–tcpClient:send(“test”);
–tcpClient:close();
else
– Error
end
end

– Make sure to enable port forwarding for port 8080 on your router, and enable
– inbound + outbound for port 8080 on your Windows/Mac firewall.
tcpServer , _ = createTCPServer(“8080”);
Runtime:addEventListener( “enterFrame” , runTCPServer);
– tcpServer.close() is done on program exit. Call the close method manually
– if you’re turning off server.

local function sendNow (event)

tcpClient:send(“test”)

end

sendTimer = timer.performWithDelay(1000,sendNow,-1)
[/code]

Thanks!
Alex [import]uid: 66618 topic_id: 19728 reply_id: 76480[/import]