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."
Related
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´m trying to do a p2p file sharing proto/software in Java.
I am interested in learning using socket so, no I will not use JXTA or any kind of API.
I read about TCP hole punching, and it may not work on all NAT types.
But I can see that Gnutella and BitTorrent always works on every machine/NAT I try.
So do they use TCP Hole Punching to initiate a connection between hosts?
Also, a code like this would do the TCP Hole Punching?
final ServerSocket s = new ServerSocket(7777);
Thread t = new Thread(new Runnable(){
public void run() {
try
{
s.accept();
}
catch(Exception ex)
{
}
}
});
Socket sock = new Socket();
sock.connect(new InetSocketAddress("IP ADDRESS", 7777), 50000);
I think that Universal Plug and Play (UPnP) is a protocol that enables you to set up port forwarding in the router programatically. I'm not sure if that is the only method that those programs use, though.
Take a look at the UPnP PortMapper project for a Java implementation.
This CodeProject article also looks good, although it is not Java: Using UPnP for Programmatic Port Forwardings and NAT Traversal.
You should have read NAT traversal on Wikipedia first.
However, in reality, the mainly used ways are UPnP, STUN, TURN, as well as ICE which is a combinition of STUN and TURN.
As TCP is a connection-oriented protocol, NATs can control it for each connection, and drop all the packets when the connection is over.
But UDP is connectionless, and the response may come from different port or different addresses (compared to your original destination). Also, there's no exact timeout for a UDP message. So usually less limitations for UDP exist on NATs.
As a result, many of these P2P implements are using UDP or some kinds of UDP-based protocols, like microTP, RUDP, UDT, or even SCTP over UDP (WebRTC is based on it).
You can also learn from articles about NAT traversals, RFCs, and BEPs (BitTorrent documents).
Edit: there's even one more interesting way - ICMP traversal. In fact ICMP (especially the TTL excceeding message) has even less limitations than UDP on NATs, for the error message can be sent from every corner of the internet, and routers with NAT cannot be aware that these messages are not the true ones. However, sending ICMP packets requires a root's permission on Unix-like systems, and Administrators' permission on Windows.
After my research I discovered that TCP is not good for bypassing NATs and TCP Hole Punching is not a 100% sucesfull technique.
The best way is to use UDP and implement a error tolerance layer over it so as it will work like TCP.
Also there are some APIs like UDT for Java. But I didnt try it yet
http://sourceforge.net/projects/udt-java/
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.