I have been given a project in which I have to share files with peers without any intermediate server. I want to know how to know how many hosts are online on the network and how to connect to them. I have to roughly make Routing table for the hosts in my computer through Java.
You need not to keep any track of routing. All you need is to know the endpoints addresses.
You may find out if a host is connected to the network by establishing a connection with this host.
You mentioned that there will be no intermediate server, so the NAT hole punching is out of scope of your question.
As the starting point look at java.net.Socket class documentation.
I'm going to assume that this is on a private network. Something that's relatively contained. Letting them find each other over the internet sounds like a nightmare.
So, given this, one model for your peers to find each other might be to select a standardised sequence of ports and an alive signal. Then when a peer searches for others, it simply goes through all the IPs on the network and makes a request on that port number. If it gets an alive signal it adds it to a table. The signalled computer would have to record the new comer as well.
You'd have to select the port sequence such that they're generally unused on the network. (Quite large) I say sequence so that there's a preference in ordering to speed up the search.
To speed up the search even more, when an alive signal is sent, it could also send it's peers table and the IPs it checked (and the ones it received in the same way). Then the new peer would only have to check new IPs on the network since old IPs with a new instance of the program would establish themselves.
Hope that helps
i'd suggest you not to go with mac address,it will be better if you turn your dhcp off of your router (if you can include one of course........but if you only can include an hub you'll be forced i guess to use mac address).and use manual addressing for your ipv4 address,and you will be able to easily connect to the other computers.
Related
I am doing an android app allowing users to play online.
Currently, I use a TCP server: when two persons are connected, the server takes care of forwarding the packets between the two clients.
I would like to replace my server by a java servlet with google app engine. This new server will just be used to connect the two players.
It would work in that way:
Player A opens a server socket and then post to the server the connection details.
When a player B wants to play against A, he asks to the server the port number of A and he connects directly to A.
The problem is that I am not sure that it will work if player A is behind a NAT. When player A opens a server socket, that opens one port of its 192.168.x.y address, but does it ask to the box a port forwarding? I assume it doesn't...
So two questions:
Is it possible to make a direct connection TCP between two devices even when there is a NAT or a firewall (I don't know how firewalls work on Android...)
If it isn't possible, what is the best solution: Is it possible to make a TCP server to ensure the exchange of the messages with app engine?
Thank you by advance.
game
Creating direct TCP connection between users under different NAT is mostly possible. There are 4 types of NAT. FC, ARC, PRC, Symmetric. If one of player A or B has symmetric NAT then it is impossible to create TCP P2P connection. In this case you will have to use a server in the middle for exchanging data between two players.
For other types of NAT combinations it is very much possible but not guaranteed. The technique that is used to create TCP P2P connection is called TCP hole punching. Read this answer to know in details about this technique.
Also creating TCP P2P connection is not related to any platform.
First, the device itself is probably not going to be the main problem. If they are at home and using WiFi, you will probably have to deal with a cable modem/DSL modem, which typically includes a firewall. Also if they are at work (or a hotel, conference center, etc.), there may be a corporate firewall to deal with.
I believe most home cable/DSL modems support uPnP (Universal Plug and Play), which includes the Internet Gateway Device Protocol (IGD) designed to let devices determine the external IP address and set up port mappings. In general you can look up NAT traversal for ways to handle connections through a home modem/firewall. I will note that corporate firewalls are a different matter and many of these techniques won't work.
So probably I would recommend you be ready for at least the following four scenarios
Direct connection with nothing creating problems. You can test this by having the server do a test connection when the player first contacts the server. If this works, things are simple.
Home NAT device that understands uPnP. If you have a 10.x.x.x, 172.16.x.x-172.31.x.x, or 192.168.x.x number (typical home WiFi), then you can try to set up the NAT traversal and if that works you can send the appropriate information to your server. It probably would be worthwhile for the server to do a test connection just to be sure that things work.
If you have a firewall that you can't get around, then make a note on the server regarding player A, and when B tries to join A's game, look and see if B will accept connections, and if so then arrange for A to connect to B instead.
If none of the above work, then have A and B both connect to the server and have the server relay messages between A and B.
If you don't want to program all those possibilities, then option 4 is the one that is most likely to work, even if it does mean extra traffic going to/from your server. But note that for corporate networks, they may simply have a rule blocking unknown connections, and there may not be much you can do.
Edit: I was able to get a simple TCP server working on Android without anything special regarding Android itself, so removed a comment saying I didn't know about that.
I'm working on a project, and basically I need this program to find a list of all connected IP addresses to a network, such as going to your network connections in Windows. I've looked all over the internet, and I cant find what I'm looking for and I hope someone can!
This program cannot just crunch numbers (such as pinging all possible IP addresses), it needs to be faster than that. Being able to just connect to the network and obtain a "list" of all IP's that it can see would be perfect. Using the docs.oracle.com webpage did what it was supposed to, but there were too many extra results (including Eth10, etc). Also, the only IP address it listed that wasnt my own didnt match any active computers, so I dont know what was up with that... (192.168.0.9 was listed, the only other active connection was at 192.168.0.10, maybe I'm missing something?).
What is a way to do this? Sorry if I'm unclear, I'm able to be clearer if there's something specific, hope this helps!
Thanks!
EDIT: I hope this helps; I want to do this in java, because for my designed program to work it needs a list of active IP addresses connectable to the active machine. Meaning that if I run it on a laptop at a school, I need all the IP addresses that I could connect to on the network. It is a network thing, but it does need to be done in java. The purpose is for a file manager, otherwise its pretty tough to explain. Does that help?
The only way to do what you are asking is via brute force. It can be done somewhat quickly by creating multiple threads that fire off TCP SYN requests to random IPs on the network (this is what NMap does). If you had access to the DHCP server then you could likely get a list from that point. I would warn you to tread very lightly. Running NMAP or doing port scans on a network is considered an attack by many network admins... you could get yourself in to trouble (they WILL notice).
As I am programming a network chat (java, but should not make a difference for the question), and wanted to use UDP, I ran into the problem of it not working over the internet. After a little research I found out that you have to have port forwarding for the specific port activated. So now it comes to my question:
Does UDP work over the Internet in a not configurable way?
For example, if I would program a whole Network Game would it make sense to use UDP? Or would I require the Player to activate Portforwarding and open the Port etc?
When would it make sense to use UDP then? And why?
I'm actually not understanding the whole point of UDP then.
For my programming point of view I would like to have a way to use it intuitive.
Like creating the DatagramSocket and the DatagramPacket, configure the Packet with the Data and the Destination and send it away over the internet.
As for my Users I don't want them to have to configure any specific things like opening the exact port they want to use etc. I just want them to use the program (server and client) and it should work.
The problem you've run into is not one of UDP vs TCP (although using the unreliable, unordered UDP as the basis of a chat application seems like an odd choice to me).
The problem is that of NAT traversal. In a nutshell, home routers perform a network function called NAT - Network Address Translation. They do it in order to use a single public IP address for all machines inside the NAT (which are given private addresses - usually 10.0.0.0 or 192.168.0.0). The router then switches the source IP address in all packets sent from inside the LAN from the private address to the public one. It uses port numbers to "remember" which machine sent what to what address, in order to perform the backwards translation when the response arrives.
The problem arises when someone wants to initiate a connection to a machine behind a NAT. Without seeing an outgoing connection first, the NAT doesn't know to which internal computer and port it should forward the packet. This is what happens to you.
There are various fixes for this issue, with the simplest one being manual port forwarding (as you've discovered), but it's a well known problem faced by any peer-to-peer application. If you need to contact a machine behind NAT (i.e. contact most home users) and you want your application to work out-of-the box (without your users fiddling with their routers) you need to research NAT traversal techniques, implement them in your application, and hope that the user's home routers support them. It's a huge pain in the neck.
EDITED: with Joachim Pileborg's correct suggestions!
UDP is often a better choice for action-based games, where it's vitally important to have updates to the client or server with the latest data about a player, player input, or the game world.
TCP begins with a 3-way handshake to establish a connection (which takes time). If your game communication protocol is via TCP, all packets in a message have to arrive before the message becomes available. Even a small amount of Internet congestion could cause your game to lag.
TCP is good for communications that MUST arrive in full.
With UDP, the client or server can send the latest player/game state in individual packets that do not depend on arriving in order. If a packet is late, or arrives out of order... it should be ignored.
UDP is good for communications that need to be fast, but losing individual packets is OK.
Both should be available in your Java platform.
Here's some further reading:
http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/
The system I am developing potentially has a very large number of clients (lets say one million) that need to periodically update a central server with some information. Clients are written in Java.
The specific use-case is that the server backend needs to have an up to date mapping of IP address to clients. But the client IPs are dynamic and subject to (effectively random) change.
The solution I have in mind requires the clients to ping the server to update their IP. The period ideally should be once every minute, but even 1 ping/10 mins is acceptable.
My questions, in sequence:
1M pings per 1 min is over 10k/sec. So first off I want to know
the approaches can scale to handle such a load. This is to know the options available.
Assuming you have more than one solution in mind, which of these
would be the most economical? The cost effectiveness is critically important. I don't have my own data center or
static and fat end-point on the net, so the server application will
need to run on some sort of provider or ultimately on the cloud.
Notes:
I considered running the server from home using my own ISP provided connection, but I am neither sure of the performance issues, nor what my ISP will think about a constant stream of pings.
I can't see how the server can auto-discover these IP changes.
Erik, your problem is much simpler than it seems to have been made to sound.
This problem been around for a decade maybe two. No need to re-invent the wheel here.
Why Polling/Pinging is a Bad Idea
The dynamic IPs provided by ISPs can have a variable lease time, but will often be at least 24-72 hours. Pinging your server every 1-10m will be a horrible waist of resources potentially making over a 4,320 useless HTTP requests PER CLIENT in a 72 hour period. Each request will be say around 300 bytes * 4,320 wasted http requests equals 1.3mb wasted bandwidth multiplied by your target client count of 1 million clients, you are talking about a monthly wasted bandwidth of ~1.2 TB! And that's just the wasted bandwidth, not the other bandwidth you might need to run your app and provide useful info.
The clients need to be smarter than just pinging frequently. Rather they should be able to check if their IP address matches the DNS on startup, then only when the IP changes, send a notification to the server. This will cut down your bandwidth and server processing requirements by thousands of times.
What you are describing is Dynamic DNS
What you are talking about is "Dynamic DNS" (both a descriptive name for the technology and also the name of one company that provides a SaaS solution).
Dynamic DNS is quite simply a DNS server that allows you to very rapidly change the mapping between a name and an IP address. Normally this is useful for devices using an ISP which only provides dynamic IPs. Whenever the IP changes for the router/server on a dynamic IP it will inform the Dynamic DNS server of the change.
The defacto standard protocol for dynamic DNS is well documented. Start here: DNS Update API, I think the specifics you are looking for are here: DynDNS Perform Update. Most commercial implementations out there are very close to the same protocol due to the fact that router hardware usually has a built in DynDNS client which everyone wants to use.
Most routers (even cheap ones) already have Dynamic DNS clients built into them. (You can write your own soft client, but the router is likely the most efficient location for this as your clients are likely being NAT'd with a private IP - you can still do it but at a cost of more bandwidth for public IP discovery)
A quick google search for "dynamic DNS java client" brings up full source projects like this one: Java DynDNS client (untested, just illustrating the power of search)
Other Considerations for your System Architecture
Lets say the IP-client mapping thing gets resolved. You figured it all out and it works perfectly, you always knows the IP for each client. Would you then have a nice reliable system for transferring files to clients from mobile devices? I would say no.
Both mobiles and home computers can have multiple connection types, Wi-Fi, Cellular Data, maybe wired data. Each of these networks may have different security systems in place. So a connection from a cellular data mobile to a wifi laptop behind a home router is going to look very different than a wifi mobile device connecting to laptop on the same wifi network.
You may have physical router firewalls to contend with. Also home computers may have windows firewall enabled, maybe norton internet security, maybe symantec, maybe AVG, maybe zone alarm, etc... Do you know the firewall considerations for all these potential clients?
Maybe you could use SIP as protocol for that purpose ?
Probably the java SIP libs already solved your problem.
Nice app by the way.
I would suggest better tweak you java program to know the IP change and then only hit the web service.
You can do it like,
on your java program initiation extract the IP of machine and store
it in Global variable or better some property file.
Run a batch process/scheduler which will check your IP every 30sec/1 minute for change.Java Quartz Scheduler will come very handy for you.
Invoke the web service in case of a change of IP.
This way it reduces your server role and thus traffic and connections.
You could create your own protocol on top of UDP, for example XML based. Define 3 messages:
request - client requests a challenge from server
challenge - server replies with challenge (basically a random number)
response - client sends username and hashed password + challenge back to the server
It's lightweight and not too traffic-heavy. You can load-balance it to multiple servers at any layer or using load-balancer.
Any average PC could handle million such hits per minute, provided you do server-side in C/C++ (I don't know about java network performance)
Please have a look at how no-ip works. Your requirement is exactly same as what it does.
Do I have the use case right? A community of users all want to receive pictures from each other? You don't want to host the images on the server but broadcast them directly to all the users?
There are two questions here. The first question is "how to know if my own WAN IP address has changed."
If you are not NATed then:
InetAddress.getLocalHost()
will tell you your IP address.
If you are NATed, then using dynamic DNS and resolving your own host name will work.
The second question is something like "How to share pictures between hosts which come and go on the internet".
The possible solution space includes:
IP Multicast, probably with Forward Error Correction and Carouseling, e.g. FLUTE.
File Swarming - e.g. bittorrent.
A Publish/Subscribe message bus solution using Jabber, AMQP, JMS, STOMP or similar. Suitable implementations include RabbitMQ, ActiveMQ, etc. JMS Topics are a key concept here.
The solution should avoid the massive overheads of doing things at the IP level.
I have been struggling with this for the entire day now, I hope somebody can help me with this.
My problem is fairly simple: I wish to transfer data (mostly simple commands) from one PC to another over the internet.
I have been able to achieve this using sockets in Java when both computers are connected to my home router. I then connected both computers to the internet using two different mobile phones and attempted to transmit the data again. I used the mobile phones as this provides a direct route to the internet and if I use my router I have to set up port forwarding, at least, that is how I understand it.
I think the problem lies in the method that I set up the client socket. I used:
Socket kkSocket = new Socket(ipAddress, 3333);
where ipAddress is the IP address of the computer running the server. I got the IP address by right-clicking on the connection, status, support. Is that the correct IP address to use or where can I obtain the address of the server? Also, is it possible to get a fixed name for my computer that I can use instead of entering the IP address, as this changes every time I connect to the internet using my mobile phone?
Alternatively, are there better methods to solving my problem such as using http, and if so, where can I find more information about this?
EDIT:
Would it be possible to have the server program running on a server on the internet somewhere. My original server would then be a client that send information to this server. This server would then pass this information to my original client and vice versa. That way, the IP address of my computer won't matter, as I only need to know the address of the server hosted somewhere on the web. Does this seem like a better solution? Where do I begin implementing such a solution?
Thanks!
When you connected to the server that serves StackOverflow, did you type in the IP address? It's 64.34.119.12, if that jogs your memory.
You probably didn't. You probably typed "stackoverflow.com". There's a huge, complex, clever, and in some ways, poorly implemented system called DNS that translates sensible and human-readable names into IP addresses.
One problem with DNS, though, is you need a "static IP", which is exactly what it sounds like: an IP address that doesn't change, which is exactly what you don't have.
So, what can you do?
You can buy a static IP account from your ISP (pretty expensive)
You can use some proxy out in the Internet (a machine that does have a static IP and is willing to bounce your packets back and forth -- I'm not aware of any service that does this for you; you could write one and put it up on Amazon Web Services or Google App Engine, both of which would be free at your level of usage, but they'd be slow, since every packet trying to cross your living room would have have to go via some data-center in Virginia).
You can keep doing what you're doing, looking in the net-configuration of your machine.
You could speed (3) up a little by having your server program look up its own IP address and print it out where you could see it and type it into the server by hand.
You can use DynDNS, as Sergey mentioned (this is the "right" solution, in that it's very general, it just might be a little complicated to set up)
You can use multi-casting.
Multi-casting is an interesting solution, and it may work for you. The idea is, when your server starts up, it announces to the net, "Here I am, I'm providing X server, here's my IP address, talk to me." The problem is, a multi-cast won't leave your living room. Obviously, if every multi-cast were spread to every computer on the Internet, the whole thing would collapse, so your router will ignore, and not route, multi-cast packets. That may or may not be a deal-breaker for you. EDIT Re-reading your question, I see it is a deal-breaker for you. I'd go with #5, but be aware there may be routing issues (address translations that prevent a server from knowing the address that other computers can find it at) or fire-wall issues (that is, your ISP may prevent your server from receiving incoming packets even if the address is correct).
using a direct socket connection with a port like 3333 is usually complicated because different network configurations.
firewalls will make a pleasure preventing the connection, or killing it from time to time.
maintaining a 2-way connection can be a nighmare. the SIP protocol is struggling with this kind of problems.
For a simple application, i suggest you look into the comet technology, where your clients can establish an http connection with a shared server. The server can then bridge commands between them.
html5 will also bring the websocket protocol to the table.
I got the IP address by right-clicking
on the connection, status, support.
Not sure about the "support" part, and I'm not on a Windows machine right now, but I think that the most easy and reliable way to figure out the IP address on Windows is to run "ipconfig" from the command line (Win+R, type "cmd", then "ipconfig" in the opened window). This, of course, should be done on the server side.
However, the problem is that depending on the ISP your IP address may be not within the Internet, but within a local ISP network (so-called NAT). In this case, you'll need to use some sort of black magic called TCP hole punching, which is very complicated and not guaranteed to work. You can figure out if your address is local or not by looking at it. For IPv4 local addresses are almost always like 10.x.x.x or 172.16-31.x.x, or 192.168.x.x. Don't know about IPv6.
You can also check your IP by visiting one of the special sites like www.whatismyip.com. If the address they tell you is different from the one you see by running "ipconfig" or looking at the connection properties, then you're almost certainly behind a NAT (or your ISP is using a transparent proxy, but that's rare).
If you are directly connected to Internet (no local addresses and NAT), then you should also check if you have any firewall software and either to configure it to allow connections to the port you use, or make sure it's in "ask the user" (and not "silently reject") mode, or just disable it completely (this may put your computer at risk, especially if there is no anti-virus software or the system isn't up-to-date).
Also, is it possible to get a fixed
name for my computer that I can use
instead of entering the IP address, as
this changes every time I connect to
the internet using my mobile phone?
Yes, it's possible. There is the thing called DynDNS, and there are DynDNS providers like DynDNS.com, where you can get a third-level domain name for free (like mycoolpc.dyndns.org). You'll have to install and configure some DynDNS client on your PC that will tell the DynDNS server its new IP each time each changed. I don't know anything about particular clients to use because I'm using the one built-in in my home router.
No need to write networking code for this, unless it really floats your boat. Take a look at SCP. http://amath.colorado.edu/computing/software/man/scp.html. There is a windows implementation where you can download putty (windows ssh client), and it is on most linux distributions. Alternatively, you could set up an FTP or SSH server on one or both of the machines.
"a fixed name for my computer that I can use instead of entering the IP address" would be a domain name, these are purchasable online for a few bucks.