Haxe: connecting to a remote host - sockets

I did the creating a client/server tutorial given here,
http://old.haxe.org/doc/neko/client_server,
but this example only really applies to the case of a local host which is of pretty limited utility. I was hoping that someone could explain how to extend this to the case of connecting to a remote host. Specifically, if someone knows how to modify this example such that I could run the server code from a laptop at home and have a friend (who knows my home ip) run the client.
Client code:
// file Client.hx
class Client {
static function main() {
var s = new sys.net.Socket();
s.connect(new sys.net.Host("localhost"),5000);
while( true ) {
var l = s.input.readLine();
trace(l);
if( l == "exit" ) {
s.close();
break;
}
}
}
}
Server code:
// file Server.hx
class Server {
static function main() {
var s = new sys.net.Socket();
s.bind(new sys.net.Host("localhost"),5000);
s.listen(1);
trace("Starting server...");
while( true ) {
var c : sys.net.Socket = s.accept();
trace("Client connected...");
c.write("hello\n");
c.write("your IP is "+c.peer().host.toString()+"\n");
c.write("exit");
c.close();
}
}
}
As a disclaimer, I know very little about communication protocols, so I apologize if the question is silly.
Edit:
If I replace "local host" with my local ip address "192.168.1.254" this still works, but if I replace "localhost" with my public ip address "206.XXX.XXX.XXX," the client does not connect (this was the first thing I tried).
I have disabled my firewall for both incoming and outgoing traffic on that port, but it doesn't seem to make a difference. Why is it that my client instance can only connect to the server instance locally? I would have though that changing the client code to use the public ip address of the computer route the request through the router.
Edit:
Turns out that it was actually working all along with the public ip address, but for whatever reason it could not connect to the router's public ip from within my local network (I still don't understand why this was a problem - maybe some weird router specific NAT problem). Using this utility:
http://www.yougetsignal.com/tools/open-ports/
I was able to verify that the relevant ports were open and connect to my server program.

In clients code in below string replace "localhost" with your IP-address:
s.connect(new sys.net.Host("localhost"),5000);
http://api.haxe.org/sys/net/Host.html
Creates a new Host : the name can be an IP in the form "127.0.0.1" or an host name such as "google.com", in which case the corresponding IP address is resolved using DNS. An exception occur if the host name could not be found.

This really depends on your home setup. Generally its a security risk to just open something on your home ip, so do this at your own risk.
Most likely you will have a dynamic ip address from your isp. This means that every time you connect to your isp your public ip may be different. Its common to use a third party service to get around this kind of thing. Many routers have a feature built in do to integrate with these providers but there are also native apps you can install. There are many services out there some free, some paid depending on what you want and who you trust eg http://www.noip.com/, http://dyn.com/dns/. These services will have getting started guides.
When its working you can change your client code from localhost to the public ip address and port you setup the dynamic dns service to expose.

Related

strange behaviour Pinging Public IP

I've tried this on 2 different networks:
Set router to respond to ping on internet port.
Lookup public IP on www.whatsmyip.com
Use PuTTy to ssh into another server and pinging the public IP from there.
In one network 1 this works, in network 2 it won't. So the question is. What can cause this behaviour?
The public IP address (the address that external sites see your requests coming from, i.e. what whatismyip will tell you) may not be one that the router is directly reachable on, for example if Carrier-Grade NAT is deployed.
ISPs may use CGNAT if they don't have enough IPv4 addresses, in order to share a single address between multiple clients.
One way to tell if this is happening would be to compare whatismyip.com to the address the router says it has on its WAN/internet interface. If they're different (and the router is connected straight to the ISP), it's probably CGNAT at play.

Using UDP between remote server and client

I am currently working on a project that needs a UDP communication between a server Amazon Frankfurt) and several hosts (Arduino). I need to be able to send JSON data from server to a host over UDP and it needs to work in real time (time is a real constraint here). Also, periodically a host will speak to server to inform server about its status.
The problem I'm facing is that although I can ping the server, when I create the UDP socket with a port, I get this error (for any port):
errno99: cannot assign requested address
I also believe that since the hosts are in different countries, I can only get router's IP. Hosts will be given to users therefore it is impossible to alter user's router by hand. I need to use something that can handle these by code.
I have been searching on Hole Punching and other techniques. I cannot decide what suits more to my scenario here. Sorry for my lack of network information, any help or guidance as "read or search these techniques" are appreciated.
This code runs on server:
import socket
import time
#Host's public IP
UDP_IP_ADDRESS = "178.243.98.86"
UDP_PORT_NO = 13000
Destination = (UDP_IP_ADDRESS,UDP_PORT_NO)
Message = "Hello, Server"
senderSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while True:
senderSock.sendto(Message, Destination)
time.sleep(1);
And this code runs on my machine:
import socket
#Server's public IP
UDP_IP_ADDRESS = "172.31.46.111"
UDP_PORT_NO = 13000
recieverSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
recieverSock.bind((UDP_IP_ADDRESS, UDP_PORT_NO))
while True:
data, addr = recieverSock.recvfrom(1024)
print "Message: ", data
Server
# Host's public IP
UDP_IP_ADDRESS = "178.243.98.86"
You cannot rely on 178.243.98.86. Your arduinos are behind one or several NATs. With NAT, when a packet leaves a network, your packets source and/or destination addresses (and most likely ports) get rewritten. When this conversion happens, a device responsible for NAT remembers this conversion, but only for a limited period of time. The period usually defaults to 24h.
In order to overcome this issue, it's up to clients to initiate conversations with the server. Introduce a new message type to your protocol saying something like hey it's me, client #34. The server should be associating source IP and port of the received message with client #34 for some period of time, like hours.
In this case the server binds a socket to an address and port as well as a client. And beware that hey it's me, client #34 sent over UDP is not encrypted and is extremely vulnerable to record and replay attacks. I believe an emergency system should be encrypted.
Client
# Server's public IP
UDP_IP_ADDRESS = "172.31.46.111"
172.31.46.111 cannot be server's public IP, because it is an address from an IPv4 private space. You probably meant to say "host's private address". It makes sense to bind to such an address. You get an error most likely because you have incorrectly determined the IP address of your host.
There are several ways to get the correct IP. If you use DHCP (you use it if you've never though about what IPs to use in your SOHO), log into your nearest router's admin interface and check the DCHP Pool. Alternatively, Linux and Windows have terminal commands to do the same. For Arduino, you have probably assigned it a static address. If so, bind to it.
You also seem to open a tcp socket on the server, and connect to it from client via udp socket. Is this intentional?
gsn

Static Way to Access a Remote Machine

There's an application. This application is run on several different client devices and it makes use of a server: that is, each of those instances of the application may connect to a server, said server being a certain remote machine that is constantly listening for incoming connections, at which point the client machine and the server machine communicate following a certain protocol.
Now, this is all nice and easy as long as I'm testing within one LAN managed by one router. I can simply set the server machine to have a static IP address and this address will just be hardcoded into the application so that every instance of it will be able to directly communicate with the server endpoint. But what I'm not sure about is what I'd do if this application was intended to run outside the limits of a single LAN with private IP addresses.
Basically, my question is what approach should I choose in order to have a static way to access a specific remote machine.
Is there any static public address that can be used to reach it? Or should I purchase a domain name and have it respond to requests from clients with the server machine's current public IP address? Or should I go on and purchase a static external IP address? Or am I simply not thinking about this the right way, and the solution should be approached from an entirely different direction?

get IP Address in Lua

i try to get the local IP from my device ( programming in Corona Lua )
till now I do with:
local myip = socket.dns.toip(socket.dns.gethostname())
but this only works on simulator
local client = socket.connect( "www.google.com", 80 )
local ip, port = client:getsockname()
but this only works when I have a Internet Connection
How could i get my local IP just in my Wifi without Internet
thx
chris
The ip of the interface you are looking for can change based on what IP address you are trying to talk to. The code below uses google's IP to select an interface and return the IP address.
It works me for me using LUA/luasocket but I haven't tried it in corona.
require "socket"
local s = socket.udp()
s:setpeername("74.125.115.104",80)
local ip, _ = s:getsockname()
print(ip)
EDIT:
You shouldn't need internet in this case because you're not actually connecting to anything or otherwise sending any packets. You will however need the interface in question to actually have an IP.

Why can't my socket programs connect to the internet?

I have begun my first course on networking this semester.
My problem is that whenever I try to connect my socket to a host outside my LAN,
network unreachable error is returned. Whether they be BSD sockets or Java sockets.
Moreover, my nmap probes also return the same error.
Once I asked a similar question here about ping probes and the answer was that my LAN proxy is rejecting ICMP requests. But there are no ICMP requests in establishing TCP connections right?
Why, on the other hand, my browser can connect to any host... although that it uses the same proxy...
Also,(please pardon me for this long doubt) when I give host name as www.google.com in my sockets, "unknown host" is returned. But my browser happily recognizes the same host.
Thank you in advance...
import java.net.*;
import java.io.*;
class Whois {
public static void main(String args[]) throws Exception{
int c;
Socket s=new Socket(args[0],Integer.parseInt((args[1])));
InputStream in=s.getInputStream();
while( (c=in.read()) != -1) {
System.out.print((char) c);
}
s.close();
}
}
Unfortunately, there may be many reasons for this behavior.
My best shot is that you're behind a firewall that's blocking any connections that are not going to port 80. In this case, you may try to connect with your program to the same network, but port 80.
Not sure why you wouldn't get name resolution for google. I'm guessing it's a bug in your code, but can't tell for sure.
Hope it helps.
Investigate and understand your network setup. How are you connected to the internet? Your workstation probably has a default route pointing to some machine again probably doing Network Address Translation (NAT) and/or running a firewall and maybe that proxy server. Find out how you do name resolution (DNS). One you figure these out you might find what you need to do to connect outside.
On the other hand, errors in the code we don't see in the question are also likely :)
There is likely a firewall that is blocking all connections to outside hosts, and an internal DNS server that does not lookup external hostnames. THis is why your socket programs can neither lookup outside hostnames nor connect to outside services.
The same restriction applies to your browser; it's just that your browser is set up to use a proxy server. This means that the browser isn't directly looking up outside hostnames or connecting to outside hosts - it is only looking up the proxy name and making TCP connections to the proxy server. The proxy then is doing the hostname lookups and making the TCP connections to the outside world, on behalf of your browser.