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/
Related
The problem: In java you can create a socket on the server with ServerSocket(0) and it will choose a random port to listen on. However when you create a socket on the client to send a message with Socket(addr, port) there is no apparent way to determine which port on the server you need to send to. I couldn't find anything about this option through web searches besides the basic "if you put 0 it will chose a random port". Does anyone know or have a resource that could explain what this scenario is supposed to look like from the client end?
Some background: I am currently converting a system from UDP to TCP. The reason I need the server to listen on a random port is that my server/client do not have a strict server/client relationship. So the "server" in this situation is really an application that I need to open multiple instances of on one PC. The old way of having predetermined send/receive ports is causing only one instance to be able to open a port and all communication is being redirected to that instance. My understanding that the best way to fix this problem is for each instance to use a different port, and the best way for that is to do ServerSocket(0). Despite including this background, I do not want comments on how messed up the situation is, only answers pertaining to the problem.
If a fixed port number is not part of the server's documented setup / protocol, then the only way for clients to figure out is to have the running/active servers publish that information in some datastore, the location and details of which are documented and known by the clients, and where that datastore is reachable for the clients.
[Or have the clients run a portscan each time they want to connect. It will work but probably not as fast as your users would like.]
And your situation is indeed messed up.
Perhaps if you are on the same IP subnet with all the servers/clients, then you could use UPnP to signal which random port new instances of your application are running on, and similarly other instances could monitor UPnP to discover this new instance.
I've never implemented UPnP in Java, but suspect libraries are out there..
eg. https://github.com/jupnp/jupnp
We are working on a Android project with the below requirements.
The application should be able to send data to all the devices which are running our application which exists in the WiFi LAN.
Some payloads are expected to be of size >= 5MB.
The data shouldn't be lost and if lost the client should know the failure.
All the devices should be able to communicate with all other. There will be no message targeted to a specific device instead all the messages should be reached all the devices in the N/W.
No internet hence no remote server.
Study we have done:-
UDP Broadcasting - UDP doesn't guarantee the message delivery but this is a prime requirement in our case. Hence not an option.
TCP - TCP guarantees the message delivery but requires the receiver IP address to be known before hand and in our case we need to send the message to all the devices inside the LAN. Hence not a straight option.
Solutions we are looking into:-
A Hybrid approach - Name one of the devices in the N/W as Server. Post all the messages to a local Server. The Server keeps a open socket to all the devices(which have our application) & when there is a message from a device then it routes the message to all the devices. The disadvantages of this approach are,
Server having multiple sockets open each per device. But in our case we are expecting devices <=5 in LAN.
Server discovery using continuous UDP broadcast.
We want to have all the data in all the devices. So if we newly introduce any device into the LAN then that device needs to get all the data from the server.
So my question, have you any time worked on these kind of hybrid approaches? Or can you suggest any other approaches?
Your hybrid approach is the way to go.
Cleanly split your problem into parts and solve them independently:
Discovery: Devices need to be able to discover the server, if there is any.
Select server: Decide which of your devices assumes the server role.
Server implementation: The server distributes all data to all devices and sends notifications as necessary. Push or pull with notifications does not matter.
Client implementation: Clients only talk to the server. The device which contains the server should also contain a normal client, potentially passing data to the server directly, but using the same abstract protocol.
You could use mDNS (aka Bonjour or zeroconf) for the discovery, but I would not even recommend that. It often createsmore problems than it solves, and it does not solve your 'I need one server' problem. I would suggest you handcraft a simple UDP broadcast protocol for the discovery, which already tells you who the server is, if there is any.
Select server: One approach is to use network meta data which you have anyway, for example 'use the device with the highest IP address'. This often works better than fancy arbitration algorithms. Once you established a server new devices would use this, rather than switching the server role.
Use UDP broadcast for the discovery, with manual heuristic repeats. No fancy logic, just make your protocol resilient against repeated packets and repeat your packets. (Your WLAN router may repeat your packets without your knowledge anyway.)
You may want to use two TCP connections per client, potentially to two different server ports, but that does not matter much: One control connection (always very responsive, no big amounts of data, just a few hundred bytes per message) and one data connection (for the bulk of the data, your > 5 MB chunks). This is so that everything stays responsive.
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 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.
I'm writting a java application, and I need to quickly discover any other running clients on any wired or wireless local networks in order to establish a TCP connection.
what's the best way of doing this? Are there libraries or code snippets that would do this?
Multicast UDP is a good way of doing this. It's used in a couple of technologies that support automatic discovery of networked devices over local IP networks (UPnP and ZeroConf).
Multicast UDP is not TCP, but it is still based on IP and, so, uses the same addressing mechanism i.e. IP addresses. Quite often it is compared to radio broadcasting i.e. a multicast sender only needs to send 1 message (i.e. it is like a broadcast) but only clients that are "tuned-in" to the multicast channel will receive it.
You can do a quick search on google or wikipedia for these as a starter, but the basic idea is as follows:
when a client starts, it sends out a multicast UDP "hello" message to some pre-specified multicast address and port (e.g. UPnP uses 239.255.255.250:1900)
existing clients are listening for incoming multicast "hello" messages on the specified address and port - when a client receives one, it sends a response to the sender
the client sending the "hello" message receives a response from each existing client on the network and is now aware of the IP address of each client
If you are looking for libraries to use, UPnP libraries can tend to be a bit heavyweight and a lot of folk generally don't like them, so ZeroConf might be a little more suitable. I don't know of any java implementations of such things but I'm sure you can find some with a little digging around.
A network scan can be very long, even longer on wireless networks. If you need them quickly thru Java you may implement a "meeting point" server on your network. This server listen to a predefined port, clients register on the server on startup and the server can distribute information about the clients on request.
HTH.
I guess you need to do a scan on your application's port on all IPs in your subnet.
Just what are the available IPs - or what is your subnet for that matter?
I'm afraid determining that could turn out to be impossible as the network is designed to be transparent to your application.
So, i'd use brute force: pick your IP and change the last byte. Might be too much, might be not enough though.
Or you send a broadcast (which usually would be targeted at x.x.x.255) and see who answers.
See Datagram Broadcasting and Multicasts. But i think that's not TCP/IP anymore.
There is a JGroups toolkit for reliable multicast communications. It allows automatic discovery of additional clients using Multicast techniques as described in other answers.
It also provides communication APIs on top of multicast sockets.
It is used in a number of projects such as JBoss, Tomcat and more to provide an infrastructure for distributed cache. See more here.