We use socket.send(packet) function in java to send a "packet" to a given port.
My problem is that i have to send a packet to a shutdown system using UDP protocol.
The problem with send() function is that first it verifies whether the host IP is
multicast or not. Now my local area network is of broadcast type. So i am having
problem is using this function.
can anyone please give me a way ?
Do you know how send udp packets in java?
First of all, broadcasting must be enabled in your network.
Then, all your servers must join to agreed multicast address.
InetAddress address = InetAddress.getByName( "230.0.0.1" );
MulticastSocket socket = new MulticastSocket( 12345 );
socket.joinGroup( address );
When you want to activate the system shutdown, send an agreed message (for example, "die") to the multicast address.
DatagramPacket packet = new DatagramPacket( buf, buf.length );
socket.receive( packet );
String received = new String( packet.getData(), 0, packet.getLength() );
The servers when accept that message should initiate a shutdown flow.
Related
can anyone show me an example in java to receive data from DatagramSocket and sending same data through Multicast Socket
Sending multicast datagrams
In order to send any kind of datagram in Java, be it unicast, broadcast or multicast, one needs a java.net.DatagramSocket:
DatagramSocket socket = new DatagramSocket();
One can optionally supply a local port to the DatagramSocket constructor to which the socket must bind. This is only necessary if one needs other parties to be able to reach us at a specific port. A third constructor takes the local port AND the local IP address to which to bind. This is used (rarely) with multi-homed hosts where it is important on which network adapter the traffic is received.
DatagramSocket socket = new DatagramSocket();
byte[] b = new byte[DGRAM_LENGTH];
DatagramPacket dgram;
dgram = new DatagramPacket(b, b.length,
InetAddress.getByName(MCAST_ADDR), DEST_PORT);
System.err.println("Sending " + b.length + " bytes to " +
dgram.getAddress() + ':' + dgram.getPort());
while(true) {
System.err.print(".");
socket.send(dgram);
Thread.sleep(1000);
}
Receiving multicast datagrams
One can use a normal DatagramSocket to send and receive unicast and broadcast datagrams and to send multicast datagrams. In order to receive multicast datagrams, however, one needs a MulticastSocket. The reason for this is simple, additional work needs to be done to control and receive multicast traffic by all the protocol layers below UDP.
byte[] b = new byte[BUFFER_LENGTH];
DatagramPacket dgram = new DatagramPacket(b, b.length);
MulticastSocket socket =
new MulticastSocket(DEST_PORT); // must bind receive side
socket.joinGroup(InetAddress.getByName(MCAST_ADDR));
while(true) {
socket.receive(dgram); // blocks until a datagram is received
System.err.println("Received " + dgram.getLength() +
" bytes from " + dgram.getAddress());
dgram.setLength(b.length); // must reset length field!
}
For more Information:
MulticastSocket
DatagramSocket
You've got that back to front. You receive multicasts through a MulticastSocket, but you don't need to send them that way: you can send them via a DatagramSocket.
See the Java Tutorial, Custom Networking trail.
I'm new to Java socket programming and I'm currently developing a small peer to peer UDP chatting room application which allow multiple clients to chat with each other.
My question is how do I make a client discover all other connected clients once he hit the connect button providing only one of the connected clients ip and port? The program only runs on local network.
You can use a unique feature of UDP which is broadcasting
On IPv4 (which you are probably using) the address for broadcasting is 255.255.255.255. Any datagram sent to that address will be sent to all UDP clients on the network for that port.
What you can do for your chat application is to have each client send a packet to the UDP broadcast identifying itself, such as maybe the nickname of the user. All the other clients will see that packet, and you will be able to parse the packet and display a list of all the chat clients on the network.
Here is an example of sending a Datagram to broadcast:
DatagramSocket s = new DatagramSocket();
s.setBroadcast(true);
DatagramPacket dp = new DatagramPacket("insert data here".getBytes(), "insert data here".length(), new InetSocketAddress("255.255.255.255", 5000));
s.send(dp);
Another client can receive it like this:
DatagramSocket s = new DatagramSocket();
s.setBroadcast(true);
DatagramPacket dp = new DatagramPacket(new byte[1024], 1024);
s.receive(dp);
The received DatagramPacket will contain the IP and port of the client who had broadcasted it.
One simple possibility would be that every client stores the other peers it knows of and passes the list to any new clients connecting.
Don't forget of authenticating your peers. You can try to use the OpenSSL (very easy) to generate some certificates and use it in association to ssl.
Edit: a bot told me to be more specific so here it is:
Local Networks (LANs) are not always safe, so, to be sure, I would recommend you use OpenSSL to generate certificates for authentication and private keys for encryption, in this way, you can communicate safely.
Python ssl module is a good example.
I'm making an application where there is a certain thread (MulticastListenerThread) which has a MulticastSocket and is listening for UDP (datagram) packets sent to the multicast group the socket is listening too.
This works. I can join a multicast group, send a message to that group and receive it through the MulticastSocket.
However, I would like to determine, from the receiver point of view, from which multicast group he received the packet. The following code gives me the address of the originator of the packet, not the multicast group:
DatagramPacket packet = new DatagramPacket(buf, buf.length);
mlcSenderSocket.receive(packet);
String src_addr = packet.getAddress().getHostAddress();
The code for sending the packet is as follows:
InetAddress address = InetAddress.getByName(dest);
packet = new DatagramPacket(payload, payload.length,
address, mlcEventPort);
LLog.out(this,"[NC] MLC packet Sent to ev port MLC " + mlcEventPort
+ " and to addr " + address);
mlcSenderSocket.send(packet);
Is it at all possible to determine which group sent the packet?
Edit:
It appears this isn't possible.
In terms of performance impact (I'm working for IoT devices), would assigning a socket per multicast group (and hence, a listener thread per group) be viable? Potentially many groups may be joined (in terms of tens or hundreds even). If it is viable, then I just need to keep the joined group address somewhere manually and refer to it as necessary.
Suggestions for other work arounds are welcome!
No group sent the packet. A socket at a specific IP address sent the packet, and the source IP address is available in the DatagramPacket. Multicast packets aren't sourced from multicast groups, they are addressed to multicast groups.
Yes it's true that you can join a MulticastSocket to multiple groups, for example:
InetAddress group;
MulticastSocket s=new MulticastSocket(12345);
NetworkInterface ni=NetworkInterface.getByName("eth1");
group=InetAddress.getByName("239.255.10.10");
s.joinGroup(new InetSocketAddress(group,12345),ni);
group=InetAddress.getByName("239.255.10.11");
s.joinGroup(new InetSocketAddress(group,12345),ni);
You then receive datagrams like this:
DatagramPacket datagram=s.receive(datagram);
Unfortunately there is no java API call in the DatagramPacket object that will allow you to determine which of the two groups was targetted by the sender, all you can get is the IP address of the network interface on which it was received (from the socket) and the sender's IP address (from the datagram).
To achieve what you want to do you're going to need to create multiple MulticastSocket objects and listen to one group per socket. You could use your own threads or NIO to listen on them all simultaneously.
I'm working on a game in Java, and I'm trying to communicate between a client and server on the same computer over the internet, and eventually between multiple computers. I used to be able to, but now the server doesn't seem to be receiving any packets from the client. I'll try to post all the relevant code.
This is on the server:
private DatagramSocket m_Socket = new DatagramSocket( 8000 );
private DatagramPacket m_DatagramPacket = new DatagramPacket( new byte[ 1024 ], 1024 );
...
while( true )
{
m_Socket.receive( m_DatagramPacket );
byte[] data = new byte[ 1024 ];
data = m_DatagramPacket.getData( );
System.out.println( "SERVER RECEIVING: " + data );
}
This is on the client:
private DatagramSocket m_Socket = new DatagramSocket( null );
private DatagramPacket m_DatagramPacket = new DatagramPacket( new byte[ 1024 ], 1024 );
...
m_DatagramPacket.setAddress( InetAddress.getByName( "72.49.50.49" ) );
m_DatagramPacket.setPort( 8000 );
m_DatagramPacket.setLength( length );
m_DatagramPacket.setData( data );
// "data" is the byte array, "length" is the length of the array
m_Socket.send( m_DatagramPacket );
I'm seeing the packet in Wireshark so I know it's sending.
EDIT: I may not understand how Wireshark works, is the screenshot below sending or receiving the packet?
Wireshark:
Firewall exception:
Port forwarding:
EDIT:
I also ran this port tester program to test port 8000 and it says the port is open
UPDATE:
For some reason I guess our routers were just refusing connections from the source local IP to the external IP destination. I can connect to the server using the local IP from the same network and using the external IP from a different network
If your client side you are creating an unbounded DatagramSocket (By passing null to the DatagramSocket(SocketAddress bindaddr)) which means there will not be any originating port for that socket. Eventhough this might work, this is clearly not the correct approach. In your client side you must do the following change.
private DatagramSocket m_Socket = new DatagramSocket();
private DatagramPacket m_DatagramPacket = new DatagramPacket( new byte[ 1024 ], 1024 );
Using the Default DatagramSocket constructor will bind the socket to next available port and will guarantee that there is a source port involved in the communication.
And your firewall exception doesn't have a Source IP and Source Port pattern or restriction. Please check based on your Router whether this is required.
Firstly, assuming that your IP and other codes you write but not in above is correct,I have done a lot of test, even tried to change the settings of the firewall.But it still works.
So, I think that maybe because of the unreliability of UDP protocol, your server sometimes can not receive the data from the client.You can just try to use TCP protocol.
Secondly, in your screenshot of PcWinTech.com v3.0.0 , it seems that your computer is in the subnetwork. So I gust that maybe the IP("72.49.50.49") is your router's IP, and I suggest you to check the settings of the router whether the router can transmit the data to your computer ,say, port forwarding.And I have just find a article that may help you.
I know its an old Question But the answer is really simple,
make the client create a request:
Client UDP ----- data Request ----> to server
the server is receiving with DatagramPacket,
after a client make a request, you can send the data using client's address and port,
Example:
byte[] buff = new byte[20];
DatagramPacket receive = new DatagramPacket(buff, buff.length, InetAddress.getByName(ADDRESS), PORT);
socket.receive(receive); // the server will wait to a client to connect
lets say the client sent Hello server
after that you could just do (the endpoint is for the client):
DatagramPacket sendData = new DatagramPacket(buff, buff.length, receive.getAddress(), receive.getPort());
socket.send(sendData)
Despite me knowing that my UDP packets are arriving as expected (via Wireshark), and having the Windows firewall turned off - my very simple Java code never receives any packets.
byte[] buffer = new byte[2048];
DatagramSocket socket = new DatagramSocket( 50000 );
DatagramPacket packet = new DatagramPacket( buffer, buffer.length );
socket.receive( packet );
I have 3 network adapters on my machine, so I tried being very specific about IPs. I tried setting the socket to look at the local address the packets were arriving on - didn't receive anything. And I also tried connecting the socket to the remote IP the packets were being sent on - didn't receive anything. All the while Wireshark is seeing all the 160 packets per second arriving...
My only other thought was that I'm not calculating the UDP checksum on the sending end (the UDP packets are assembled 'by hand' on an embedded system), it is just being set to 0x0000 - does DatagramSocket discard UDP packets without a checksum!?
I wrote a simple test server to aid diagnosing the problem per #Andreas' suggestion.
InetAddress outAddr = InetAddress.getLocalHost();
InetAddress inAddr = InetAddress.getByName( "192.178.178.0" );
byte[] buffer = ( "Hello" ).getBytes();
DatagramSocket socket = new DatagramSocket( 50000, outAddr );
while ( true ) {
DatagramPacket packet = new DatagramPacket( buffer, buffer.length,
inAddr, 50000 );
socket.send( packet );
try {
Thread.sleep( 500 );
} catch ( InterruptedException e ) {
// Ignore.
}
}
Wireshark dutifully notes that it is receiving them all - but my client still doesn't, even when the receiving IP is explicitly set:
InetAddress inAddr = InetAddress.getByName( "192.178.178.0" );
DatagramSocket socket = new DatagramSocket( 50000, inAddr );
...
socket.receive( packet );
Something odd I have just noticed though, when I check which NetworkInterface is being used for sending and receiving, Java reports back the right one (the one 'owning' 192.178.178.0) - but Wireshark only sees my test server packets on a different network device. Any ideas on what is going on?
Ok, well this is embarassing. I turned off the Windows firewall for Private and Work networks - but it turns out Windows considered the one I actually needed to be a Public network...
It works fine now. I considered deleting this question, but hopefully it will help some other muppet.