Most efficient way to tackle NATs? - java

I'm trying to make a distributed system, where each node has it's own server and client.
Let the server client for one node be AServer and AClient, and for the second node be BServer and Bclient.
Currently, the operation is such, that the AClient sends datagram packets from any free port say Y, and is always listening (with AServer) on a particular port say X. The BServer side always replies to packet address at a predefined port X.
This does not work behind a NAT because of the port mappings that NATs create. Since the X for the NAT at which BServer replies may not be mapped to the correct AClient
So these are the solutions and problems I thought of to solve this issue,
Any new ideas are more than welcome, and I would want to hear about the efficiency as well as ease of implementation for all of these ideas.
Solution AClient Sends packet from the port that AServer listens at. BServer replies to the port associated with the Apacket. (I tried this out, but it showed errors, I am not sure if UDP is fully duplex or how well multiple writes on a socket are handled)
Use jpcap to create an Apacket which has it's source port as the port I am listening at(say X), and is sent through a different port(say Y), so that when the BServer replies to the Apacket port, it reaches the port I was listening at(X).
Create an AClient thread which listens for a response from the BServer, and then sends that response to itself as loopback on the port it's AServer listens at. (How efficient is it to send loopback packets?)
Create an AClient thread which listens for a response from the BServer, and then use thread synchronization to prevent multiple simultaneous writes on the object being written to from the information received with the AClient and the AServer.
I'm afraid of the answer being point 4. Also, feel free to ask for any code if needed!

Related

UDP Packet loss when sending possible?

My professor gave me the task to realize a file transfer via UDP, which implements the protection mechanisms for reliability like as TCP (CRC check, correct packet order, ACK/NACK). I got some default classes from him (Socket & Channel) to simulate packet loss and delay on local machine. A packet loss when sending the packets is also simulated in its classes. However, this means that if an ACK is not sent correctly i can't notice it either, since an ACK from server to client is not confirmed with an ACK for an ACK from client to server.
I thought that packet loss can only happen when receiving packets.
Is it possible in real cases that an packet can be lost while sending without getting a code exception?
Greetings
Is it possible in real cases that an packet can be lost while sending without getting a code exception?
Easy. Simply send the packets from your application faster than the network interface can forward these. Of course any intermediate systems on the way (i.e. switches, routers) might also get overloaded and loose packets.
But at the end it does not actually matter how the packet is lost, i.e. if one the local system while sending, on the remote system while receiving or in between while forwarding. One simply cannot assume that a successful send will be matched by a successful recv.
IP packets contain the transport protocol (TCP, UDP, etc.) in their payload, and you lose IP packets all the time due to things like oversubscription at some point in the path. QoS, controls can also use something like RED that purposely discards packets in order to keep queues from filling and doing tail-drop. TCP can realize that TCP segments (not packets) are lost and resend them, but UDP has no mechanism to realize that its datagrams (not packets) are lost. UDP is a fire-and-forget protocol.

Java Multicast send and receive

Working on a little app in Java. Suppose I have three nodes, A, B and C, Each is listening on a multicast socket to the same group. Suppose one of them needs to send a message to that group, can it merely pop that message out on the same socket on which it's listening or does it need to create a second socket connected to the group and transmit on that? Have not yet googled me up a definitive answer on that
It can use the same socket for sending and receiving.

UDP Datagrams in gaming, what happens when they get lost?

Let's say you want to make a real-time game, perhaps a 2D topdown game.
Things you would do in the game to keep it simple are:
Connect to the server
Move the player with the keys
Possibly press space bar to attack
Send a chat message
But what would happen if a datagram from any of these situations get lost?
What would you do?
1) Connecting to the server
If you send a UDP datagram to the server, the server would take your IP and port and then create a player
based on an ID it gives you, this it how it identifies you every time it receives a datagram from you.
But what if upon "connection" (not actually a connection, just a udp datagram that says 'make me a part of your server'), this initial datagram gets lost. Is it right to say that you would just resend it if after a certain period of time you did not receive a reply back from the server?
2) Moving the player/attacking
If at any time we move the player/press a movement key/attack key, we would send a keystroke
to the server telling it what key we pressed/released.
The server would then relay this to all the other clients.
But what if this keystroke datagram gets lost? Either upon client->server or server->clients.
Because keystrokes are happening all the time, is it efficient to just resend it all the time?
Or would we just ignore the fact that it got lost along the way because there's a chance that if you press a key again it will most likely make it the next time?
3) Sending a chat message
This would be something that MUST reach the server.
If it got lost along the way, after a certain period of time if we did not receive a reply from the other side/receiving end, do we re-send it?
TL;DR
Is it okay to just keep resending datagrams if we know after a certain period of time it did not reach?
And also, what about confirming if a datagram got successfully sent?
If client sends a chat message to the server, and the server receives it, should the server send a reply back to the client to confirm that it received it? What would happen if that reply got lost, what then?
Typically games using UDP have an application level protocol on-top so they can send some messages reliably and others not. If they wanted to send everything reliably they would be better off using TCP. However fast-paced games can not afford the delay TCP introduces and if the packet does get lost it's often too late to re-send it!
One way to implement reliable messages is, like you suppose, to send an ACKnowledgment reply that this particular packet was received - but what if that gets dropped you ask? The sender of the reliable packet typically re-sends a certain number of times (e.g. 3 times) and if no ACK is still received the sender then assumes the peer has dropped.
An excellent place for articles and game networking including how to minimise data sent is Shawn Hargreaves blog. (This is focused at C# XNA but the same logic applies irrespective of language/framework/platform).
Lastly:
Game network programming for fast paces games is hard. If your game is slow and/or turn based consider TCP and a lock-step approach which makes things considerably easier.
Don't re-invent the wheel, there are libraries that do things such as implementing reliability on top of UDP for when you need it, e.g. FalconUDP. Though this is a .NET one - I would like to see a Java port :)
If a datagram gets lost there is nothing the receiver can do, because he doesn't know about it. It's up to the sender to re-send, and it's up to you to design an ACK-based or NACK-based protocol so that the receiver knows when to do that.
Whether it is okay to just keep resending UDP datagrams depends on how the server treats the data in the datagrams. For example, if you resend a chat message, and the server receives both the original message and the resent message, does the server display the message twice? Note that you might end up resending even if the original message was received, because the reply to the original message might have gotten lost or delayed.
The best bet is to use TCP instead of UDP, since TCP has already solved all these problems for you. World of Warcraft, for example, started with TCP for chat and UDP for gameplay, and eventually converted to TCP for everything.

Java: How to make a multicast IP InetAddress exclusive?

I'm trying to make a multicast IP exclusive, i.e. it can be "locked" and when it is "locked", no more MulticastSocket can join it.
Is it possible? How do I do it? Here's some code to explain my case:
String multicastIP = "224.0.0.1"; //multicast IP to "lock" later
InetAddress group = InetAddress.getByName(multicastIP); //create group
MulticastSocket multicastSocket = new MulticastSocket(8800); //Create a MulticastSocket using port 8800
multicastSocket.joinGroup(group); //join the group
//This is the part where I want to "lock" the group/IP
Additional information:
I'm developing a network game where the single server to multiple clients broadcasting scheme is done via this method.
There was a time we created two servers (that happen to have the same multicast IP) and incidentally, the clients listen to both servers, receiving messages from both servers.
What we want to happen is to make the clients listen only to their respective servers.
Thanks! :D
Multicast won't do this for you.
You will have to examine each incoming packet when you receive it and match it against the (source address, source port) tuple the client is sending from.
Honestly I don't think there is much advantage to using muticast for this. One approach I have seen is to use multicast for service discovery, and then use unicast for the "real" protocol once you have discovered it.
Edit: For a LAN application, multicast may be acceptable. I would just be careful not to broadcast too much. (multicasts are essentially broadcasts to most switches; they are filtered out by the NIC rather than the network) That is, ideally make sure the server is the one sending the multicast traffic while the clients unicast updates to the server. (if every client multicasts state updates that all other clients can see, what's the purpose of having the server?)

Java: Determine receiving address when receiving with MulticastSocket

I am using MulticastSocket to receive UDP Multicast packets. How can I determine to which address such a packet was sent? With the methods provided, I am only able to determine the sender address.
Of course, I am the one who sets the To-Address when creating the listening socket, but can I really be sure about this? What about broadcast packets? What about packets that somehow end up here?
I really want to distinguish if the packet was REALLY multicast.
Thank you!
Update: Currently it seems like unicast packets just sent to that port also end up in the multicast sockets receive() :( Binding to devices also gives me no better results
I'm a bit fuzzy on the details but a multicast packet will have been sent to the ip/port combo you subscribed to (and this info will be in the packet, somewhere), assuming you managed to have a clear path of intermediary routers that understand multicast. If you want to make sure the multicastsocket is receiving from the right network interface, there's a bunch of functions to bind it to a specific interface.
I don't think you have any way of knowing if the packet was "really" multicast, i.e. someone could always forge one, since there's no real security built in.

Categories