I'm experimenting with LuaSocket for a project I'm working on. I've chosen UDP as my protocol.
Looking for docs and tutorials online, I've attempted to create a client-server pair for testing and learning.
According to what I've read, the following code should work. However, only the server seems to be working properly. The client sends a message, but it will not receive the reply from the server.
Thank you for any help anyone can provide.
Server:
-- Server
#!/usr/bin/env lua5.1
local socket = require("socket")
udp = socket.udp()
udp:setsockname("*", 53474)
udp:settimeout(0)
while true do
data, ip, port = udp:receivefrom()
if data then
print("Received: ", data, ip, port)
udp:sendto(data, ip, port)
end
socket.sleep(0.01)
end
Client:
-- Client
#!/usr/bin/env lua5.1
local socket = require("socket")
udp = socket.udp()
udp:setpeername("127.0.0.1", 53474)
udp:settimeout(0)
udp:send("Data!")
data = udp:receive()
if data then
print("Received: ", data)
end
The timeout value you set is 0, which causes the client timeout every time.
To fix it, give it a positive timeout value:
udp:settimeout(1)
Or set it to nil or a negative value, so it blocks indefinitely:
udp:settimeout()
or
udp:settimeout(-1)
Related
Getting error of "Error code: -9989(0x-2705), Connection refused" by using BlueSocket framework and connecting between Mac and IOS.
Here is the logic:
I am treating Mac as a server:
// making TCP IPV4 socket
try self.listenSocket = Socket.create(family: .inet, type: .stream, proto: .tcp)
// start lisening port of 8888
try socket.listen(on: self.port)
// accept client connection when there is
let newSocket = try socket.acceptClientConnection()
// keep opening and reading data ....
iPhone as a client:
self.socket = try Socket.create(family: .inet)
try self.socket?.connect(to: ip, port: 8888)
try self.socket?.setReadTimeout(value: readWriteTimeOut)
try self.socket?.setWriteTimeout(value: readWriteTimeOut)
self.socket?.readBufferSize = Socket.SOCKET_MAXIMUM_SSL_READ_BUFFER_SIZE
client first time connect with the server works fine.
after the server receives data, client-side automatically closes the socket.
client tries to connect the server again to send back data by using same code above.
Then error displays!
I think by default when the server-side uses socket.listen, it has SO_REUSEADDR set to true
Need suggestions on how to resolve this issue. Thanks!
Just need to make sure while loop for socket.acceptClientConnection() is opening all the time....
I'm not sure NodeMCU can do this, I want to open a TCP port on two ESP8266 devices connected to the same network, data sent from either arrives on the other.
I've tried net.createServer and net.createConnection, neither of which seem to do the job, I assume net.createServer is browser only.
Example below of just using one device, and is just to test if I can send data from putty, but I get no output..
note: waiting for wifi.sta.status() == 5 before launching the server makes no difference.
wifi.setmode(wifi.STATION)
wifi.sta.config(ssid,pwd)
wifi.sta.connect()
wifi.sta.setip({ip=ip,netmask="255.255.255.0",gateway=gateway})
srv=net.createServer(net.TCP)
srv:listen(port,function(conn)
conn:on("receive", function(client,request)
print(request) -- ! never happens
end)
end)
That definitely works. We had something very similar just the other day at https://stackoverflow.com/a/36769999/131929.
server.lua
-- establish connection to AP
...
srv=net.createServer(net.TCP)
srv:listen(5555, function(c)
c:on("receive", function(sck, data)
print("received: " .. data)
sck:send("echo: " .. data)
end)
end)
client.lua
wifi.setmode(wifi.STATION)
wifi.sta.config("test", "password")
wifi.sta.setip({ip="192.168.0.199", netmask="255.255.255.0", gateway="192.168.0.1"})
srv = net.createConnection(net.TCP, 0)
srv:on("receive", function(sck, data) print("received: " .. data) end)
srv:on("connection", function(sck)
sck:send("foo")
end)
srv:connect(5555,"192.168.56")
Testing
I first started the server then sent TCP data from the command line
$ echo "foo" | nc -w1 192.168.0.56 5555
echo: foo
Ok, first test successful. Then I started the client on a second ESP8266 in the same subnet. Both were connected to their respective ESPlorer at the time. The server reported
received: foo
while the client reported
received: echo: foo
Be sure to also look up the functions used in this simple test in the API documentation at http://nodemcu.readthedocs.org/en/dev/en/modules/net/.
my udp code doesn't work when sending from computer 1 to computer 2, but it works sending from comp 2 to comp 1. I have tried both on the same computer, works fine as expected. The computers are connected through ethernet on a lan, and windows picks up the computers and lets me log in and read/write to/from the computers.
Server:
local socket = require "socket"
-- begin
local udp = socket.udp()
udp:settimeout(1)
udp:setsockname('*', 12345)
local data, msg_or_ip, port_or_nil
local cmd, parms
local running = true
print "Beginning server loop."
while running do
data, msg_or_ip, port_or_nil = udp:receivefrom()
if data then
print(data,msg_or_ip,port_or_nil)
udp:sendto(data,msg_or_ip,port_or_nil)
elseif msg_or_ip ~= 'timeout' then
print("Unknown network error: "..tostring(msg))
end
socket.sleep(0.01)
end
Client:
local socket = require "socket"
local address, port = "192.168.137.161", 12345
udp = socket.udp()
udp:settimeout(1)
while true do
udp:setpeername(address, port)
udp:send(io.read())
udp:close()
--udp:setsockname("*",12345)
data, msg_or_ip, port_or_nil = udp:receivefrom()
print(data, msg_or_ip, port_or_nil)
udp:close()
end
The client sends the message, server picks it up, and should echo it right back, but the client spits out
nil refused nil, with the tab between nil and refused.
I think this is mostly just something with sending from the server computer to the client computer, since it should just echo the data.
I could see how this problem would be hard to answer, due to not everyone having full access to two computers at once. For the record lua 5.1 is used on both, socket is v2.0.2 on both as well.
for all who were wondering, it was because I closed the socket. nothing major.
Working with LuaSocket, this code works:
local socket = require'socket'
local server = socket.bind('*',51423)
local client = server:accept()
but this code fails:
local socket = require 'socket'
local server = socket.tcp()
server:bind('*',51423)
local client = server:accept()
--> lua: /tmp/server.lua:4: calling 'accept' on bad self (tcp{server} expected, got userdata)
Yet the documentation for TCP bind implies that the latter should work, stating:
"Note: The function socket.bind is available and is a shortcut for the creation of server sockets."
How can I convert a generic "master" object into a server?
The motivation for this is the desire to add a timeout on the bind operation itself:
local socket = require'socket'
local server = socket.tcp()
server:settimeout(2/1000) -- Only wait 2ms when attempting to bind
server:bind('*',51423)
The answer is at the top of the same documentation page (oops):
"A master object can be transformed into a server … with the method listen (after a call to bind)"
It would seem that s = socket.bind(…) is actually equivalent to:
s = socket.tcp()
s:bind(…)
s:listen(32)
I'm not sure why they are split into two functions, but modifying the code to add listen() causes it to work:
local socket = require 'socket'
local server = socket.tcp()
server:bind('*',51423)
server:listen(32)
local client = server:accept()
i want to check my server connection to know if its available or not to inform the user..
so how to send a pkg or msg to the server (it's not SQL server; it's a server contains some serviecs) ...
thnx in adcvance ..
With all the possibilities for firewalls blocking ICMP packets or specific ports, the only way to guarantee that a service is running is to do something that uses that service.
For instance, if it were a JDBC server, you could execute a non-destructive SQL query, such as select * from sysibm.sysdummy1 for DB2. If it's a HTTP server, you could create a GET packet for index.htm.
If you actually have control over the service, it's a simple matter to create a special sub-service to handle these requests (such as you send through a CHECK packet and get back an OKAY response).
That way, you avoid all the possible firewall issues and the test is a true end-to-end one. PINGs and traceroutes will be able to tell if you can get to the machine (firewalls permitting) but they won't tell you if your service is functioning.
Take this from someone who's had to battle the network gods in a corporate environment where machines are locked up as tight as the proverbial fishes ...
If you can open a port but don't want to use ping (i dont know why but hey) you could use something like this:
import socket
host = ''
port = 55555
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(1)
while 1:
try:
clientsock, clientaddr = s.accept()
clientsock.sendall('alive')
clientsock.close()
except:
pass
which is nothing more then a simple python socket server listening on 55555 and returning alive