Client-Server chatting in Lua - networking

Server Program
local socket = require("socket")
local server = socket.try(socket.bind("*", 1234))
local ip, port = server:getsockname()
while 1 do
local client = server:accept()
client:settimeout(10)
local line, err = client:receive()
print (line)
print("Enter input:")
if not err then client:send(io.read().."\n") end
client:close()
end
Client Program
local host, port = "*", 1234
local socket = require("socket")
local tcp = assert(socket.tcp())
tcp:connect(host, port);
tcp:send("Connection Established\n");
while 1 do
local s, status, partial = tcp:receive()
print(s or partial)
print("Enter input:")
tcp:send(io.read().."\n");
if status == "closed" then break end
end
tcp:close()
The server program can send the message to client but the client can't send message to server. Is there any way to do it..??

I don't have enough reputation to comment, but after 10 seconds or the server sending a message, whichever comes first, the server closes the connection. The client doesn't attempt to send a message until after the server has sent a message, and the way you've written your code the server immediately closes the connection at this point. If you want the two to communicate you'd be better off accepting the client outside of the loop like so:
Server Program
local socket = require("socket")
local server = socket.try(socket.bind("*", 1234))
local ip, port = server:getsockname()
local client = server:accept()
client:settimeout(10)
while 1 do
local line, err = client:receive()
print (line)
print("Enter input:")
if not err then client:send(io.read().."\n") end
end
client:close()
Now, this brings up the issue in which the server lacks the code to realize a client has disconnected and needs to find a new client, however it shouldn't be that difficult to implement.

Related

When does a broken pipe occur in a TCP stream?

I am trying to write an echo server in Rust.
use std::net::{TcpStream, TcpListener};
use std::io::prelude::*;
fn main() {
let listener = TcpListener::bind("0.0.0.0:8000").unwrap();
for stream in listener.incoming() {
let stream = stream.unwrap();
println!("A connection established");
handle_connection(stream);
}
}
fn handle_connection(mut stream: TcpStream) {
let mut buffer = [0; 512];
stream.read(&mut buffer).unwrap();
println!("Request: {}", String::from_utf8_lossy(&buffer[..]));
stream.write(&buffer[..]).unwrap();
stream.flush().unwrap();
}
The first request with nc localhost 8000 is working as expected but subsequent request aren't. What am I doing wrong? Is the problem in how the server is reading requests from clients? Though there is no error server side.
I am sending data by typing them on the terminal:
$ nc localhost 8000
hi
hi
hello
# no response
# on pressing enter
Ncat: Broken pipe.
A 'Broken pipe' message happens when you write to a stream where the other end has been closed. In your example, your handle_connection routine reads a single buffer from the client, copies that back to the client, and then returns, which will close the stream. When you run netcat from the terminal like that, the terminal defaults to line buffering, so each line you type will be sent to the server as a single write.
The first line is sent, read by the server, echoed back, and then the server closes the connection. Netcat gets a second line, writes that to the socket, and gets a 'Broken pipe' because the server has closed the connection.
If you want your server to read multiple messages, you need to have your handle_connection routine loop, reading from the stream until it gets an EOF.

Lua TCP/IP simple Client Server connection

I'm looking for a simple client-server connection in Lua. Due to bad online documentation I'm quite helpless. I found two threads here in stackoverflow but they didn't help much. Here is what I have so far:
Client:
local socket = require("socket")
local host, port = "192.168.100.47", 51515
local tcp = assert(socket.tcp())
tcp:connect(host, port);
tcp:send("hello world\n");
while true do
local s, status, partial = tcp:receive()
print(s or partial)
if status == "closed" then
break
end
end
tcp:close()
Server:
local socket = require("socket")
local server = assert(socket.bind("*", 51515))
local tcp = assert(socket.tcp())
print(socket._VERSION)
print(tcp)
while 1 do
local client = server:accept()
line = client:receive()
client:send("it works\n")
end
Here is a working client/server example, which is based on luasocket documentation and SO answers. If you have issues with getting it to work, you need to provide specific details about those issues.

Creating an HTTP server in NodeMCU through an access point created by the board

I am coding a robot, using NodeMCU (ESP8266) and want it to be remote controlled. My current solution is connecting to a nearby router, to the internet and creating a TCP HTTP server. Data is streamed from the mobile device (remote) to the NodeMCU (robot) via HTTP requests. The remote is loaded onto the mobile device through a browser with HTML/CSS/JavaScript.
What I want instead is for the NodeMCU to create its own hotspot, because:
A router is not required
The connection is more direct
I want the same TCP HTTP solution, but I don't know how to serve a webpage through a custom hotspot.
This is my code:
-- Connect to router
wifi.sta.config("ssid","password")
wifi.sta.connect()
-- Code for waiting for connection
-- Create server
srv = net.createServer(net.TCP)
srv:listen(80,function(conn)
conn:on("receive",function(conn,payload)
for line in string.gmatch(payload,'[^\r\n]+') do
s = string.find(line, "GET /&")
-- If query is there, control robot
if s ~= nil then
-- Do stuff with query
break;
-- If no query, serve webpage
else
file.open("index.html", "r")
while true do
s = file.read(1460)
if s == nil then
break
end
conn:send(s)
end
file.close()
end
break
end
conn:on("sent", function(conn) conn:close() end)
end)
end)
Creating custom hotspot:
wifi.setmode(wifi.STATIONAP)
cfg={}
cfg.ssid="custom_ssid"
cfg.pwd="custom_password"
wifi.ap.config(cfg)
So how do I make it so the mobile can access the server? How do I get/set the IP of the server? Basically, I just need it to work. Thanks!
Not sure I fully understand but I believe you're really close. Check the documentation for the AP functions at http://nodemcu.readthedocs.io/en/latest/en/modules/wifi/#wifiap-module.
wifi.ap.config(cfg) sets SSID and pwd as you noted. Your client then connects to this AP by joining the network.
If you then print wifi.ap.getip() you'll see that the device has the IP address 192.168.1.4 by default. Hence, for clients which joined this network your server is reachable at 192.168.1.4:80 unless you set a custom IP explicitly.
However, the sending of data seems broken. You have multiple conn:send(s) (in the loop) yet you also have conn:on("sent", function(conn) conn:close() end) which means that the connection will be closed after the first conn:send! Check the docs at http://nodemcu.readthedocs.io/en/latest/en/modules/net/#netsocketsend for an example as for how to do that properly.

Get client ip on server side with lua

I want to know the client ip that connects to my lua server to find out if the connection comes from internet or intranet.
srv=net.createServer(net.TCP)
srv:listen(80,function(conn)
print(conn)
conn:on("receive",function(conn,payload)
ip = conn:getpeername()
print(ip)
conn:send("<h1> TEST.</h1>")
end)
conn:on("sent",function(conn) conn:close() end)
end)
I get the error:
PANIC: unprotected error in call to Lua API (stdin:2: attempt to call method 'getpeername' (a nil value))
Note: Im using this on the esp8266 chip and I have no experience with lua!
How can I find the IP of the client who connects?
With the new patch: ip,port = conn:getpeer() works.

H2 Database Server to serve TCP clients from connection pool

I have a H2 server that I start from console. The client from different machine accesses the server and calls a function alias (registered at the database). The problem is, this function is called more than a million times. So, in this case, the connection timesout but then I solved it with changing the client connection string to have AUTORECONNECT=TRUE. This solves the problem but adds a reconnection time delay (which I want to avoid).
Is there any flag/command that we can use to specify with Server to dedicate X amount of connections?
Also, I looked into the possibility of starting the server from within Application. Like,
JdbcConnectionPool cp = JdbcConnectionPool.create(
"jdbc:h2:tcp://IPADDRESS:9092/~/test", "sa", "");
cp.setMaxConnections(MAX_CONN_IN_POOL);
// start the TCP Server
Server server = Server.createTcpServer().start();
Connection conn = cp.getConnection();
Statement stat = conn.createStatement();
stat.execute("SELECT myFunctionAlias(arg)");
cp.dispose();
server.stop();
The above sample code does start the server and will only run once. I want the server to be open and keep listening to clients, and serve them from the connection pool. Any pointers?
You should start the server in AUTO_SERVER mode, this way a leader election algorithm will elect a leader who will read the database file and open a TCP server for all other clients.
Thsi way the server will be really fast to read the file while other clients will be as fast as the network is.
This is transparent to the user as long as you use the same connection string.
Connection connection;
String dataBaseString = "jdbc:h2:/path/to/db/" + File.separator + "db;create=true;AUTO_SERVER=TRUE;AUTO_RECONNECT=TRUE";
try
{
Class.forName("org.h2.Driver");
log.info("getConnection(), driver found");
}
catch (java.lang.ClassNotFoundException e)
{
log.error("getConnection(), ClassNotFoundException: " + e.getMessage(), e);
Main.quit();
}
try
{
connection = DriverManager.getConnection(dataBaseString);
}

Resources