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.
Related
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.
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!
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?)
I am looking for a way to not receive broadcast messages with DatagramSocket. The implementation seems to hide the destination address so I cannot use that as a filter. Setting setBroadcast seems to do nothing.
I have a socket bound in a local ip address but it still receives all the broadcast messages from the subnet.
InetAddress addr = InetAddress.getByName("1.2.3.4");
InetSocketAddress sockaddr = new InetSocketAddress(addr, 12345);
DatagramSocket socket = new DatagramSocket(sockaddr);
What would be the easiest way to filter the broadcast messages and only receive messages sent directly to my ip?
EDIT: The short answer is no. This question stemmed from an architecture where we had custom routing of UDP messages and some nodes in the subnet were not necessarily broadcasting or interested in the broadcasts. There were other issues with it and we ended up modifying the architecture a bit.
Here is a simple Java application using UDP packets that shows using the DatagramPacket class to send and received UDP datagrams and querying the various fields such as the sender's IP address. So if you can use the IP address of the sender as an indication as to whether the message should be processed or ignored, this should help you out.
If you are using class DatagramSocket, the UDP datagram received includes the header information and you can parse it out according to this DatagramSocket documentation. This article from wikipedia on User Datagram Protocol discusses the UDP datagram format and structure.
So the question is whether you can have a list of allowed senders of messages or some way to filter out not allowed senders.
Another option would be to provide some kind of identification information or signature in the datagram that will allow you to identify allowed datagrams versus those to be ignored. You do not mention the types of broadcasts but perhaps you can ignore anything that is less than a specified number of bytes or something similar. Or perhaps you can ignore any datagrams from a certain range of ports or allow only datagrams from a specific range of ports.
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.