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?)
Related
I'm programming a chat using MulticastSocket and I will count the number of clients joined on this.
try (MulticastSocket clientSocket = new MulticastSocket(PORT)) {
clientSocket.joinGroup(address);
Does MulticastSocket have some function for this purpose?
It is not technically possible. The way that the IP multicast protocol works, the endpoints don't know what other endpoints are in a multicast group.
As this Wikipedia page describes it:
IP multicast operation does not require an active source to know about the receivers of the group. The multicast tree construction is receiver driven and is initiated by network nodes which are close to the receivers. IP multicast scales to a large receiver population. The IP multicast model has been described by Internet architect Dave Clark as, "You put packets in at one end, and the network conspires to deliver them to anyone who asks."
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 have a machine with two network interface cards. I was wondering if I want to send out a multicast message to one of the LANs - is it mandatory to use the machine's ip in that LAN, or can have as input ant ip from the LAN?
That is, let's say the machine's IP is:
190.20.20.20
and another machine in that LAN is:
190.20.20.1
can I put:
multcastiScoket.setInterface("190.20.20.1");
If so - does that machine have to be on turned on?
Thank you.
While multicast has its own routing pecularities, it is important to understand that an explicit choice of the NIC (for both sender and receiver) is important and does make a difference (unless you want to rely on a particular OS'es "automagic" implementations, which can get very tricky in production).
Firstly, let us clarify, that java.net.MulticastSocket can and is used for both: sending and receiving messages (this does not mean that sending MC, and receiving MC are similar; a receiver must perform IGMP joins etc, is visible on ip maddr etc. etc.).
In general, the more you specify while creating these sockets the better (or else you will be at the mercy of the OS, with not-so-easy to debug situations bound to happen).
For the Receiver socket you should:
specify the port (in constructor); firewall should be open for inbound udp traffic on that port,
specify the interface (via socket.setNetworkInterface); else OS will take one of the available interfaces (check via ip maddr),
specify the MC-group (e.g via socket.joinGroup(InetAddress.getByName("230.0.0.0")) (this triggers the IGMP mechanism, visible via tcpdump -i your_interface -n ether multicast)
For the Sender socket you should similarly,
specify the MC group (same command),
specify the interface (same command)
I'd put two arguments if favor of the above,
Tested simple senders and receivers on CentOS 7 with two NIC's (enp0s3, and enp0s8) (code here). Only by setting NIC expliclity on the receiver was I able to confidently tell on which NIC the IGMP join will be issued, and on which NIC the program will be listed (via ip maddr) as having joined the MC group; by setting the Sender onto specific NIC's it is readily verified, that a send on enp0s3 will only reach a receiver on enp0s3, and not enp0s8 (similarly, the tcpdump shows the packets as outbound on the chosen interfaces). This is so, of course, without starting to play with MC routing on the OS, which can be made to route the packets as wished for,
You may imagine a setup like yours, where two different NICs will lead to completely separated LAN's, which may further have all/complete elements of MC routing (designated routers, perhaps rendezvous points etc). Thus, selecting the proper NIC for IGMP joins is essential and determines everything; if these are issued to wrong NIC, you may not be able to receive MC traffic; if they are issued to both NICs, you may get more than you want.
I hope this helps (even if the question is 6 years old by now);
IIRC MulticastSocket is for receiving multicasted messages, and you need to configure it with setGroup to listen for multicast messages bound for a specific multicast IP address.
If you want to send a multicast message things are much simpler: you just send your message to that specific multicast IP address and the router/gateway will handle the actual multicasting logic for you. (So you do need to have a router/gateway which supports multicasting properly.)
EDIT: the Java tutorials cover this topic as well: http://docs.oracle.com/javase/tutorial/networking/datagrams/broadcasting.html
The IP address in the setInterface() method is the address of one of your own interfaces. This is used in the case where you have multiple NICs, all connected to different subnets, and you want your multicast join and leave group messages to go out to a subnet that isn't the default route as per the IP routing tables.
In the case you mention there is no need to call setInterface() at all.
If you want a machine to receive messages it does have to be turned on.
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.