Multicast to directly connected WIFI device - java

I have a WIFI device, that I am experimenting with. From my macbook I can make a direct connection to the device over wifi. After I have WIFI connection I should be able to communicate with the device over multicast.
However, as soon as I try to send a datagram packet to the camera when I am connected I get some IOException:
java.io.IOException: Can't assign requested address
I reviewed some networking settings and found out that Multicast is enabled for my laptop, also I added the multicast address that is used (239.255.255.250) to the routing table. (Read this somewhere) Still no luck...
Why do I get this exception from my application?
Here is the code I use to connect:
DatagramSocket socket = null;
DatagramPacket packet = null;
try {
socket = new DatagramSocket();
InetSocketAddress iAddress = new InetSocketAddress("239.255.255.250", 1900);
packet = new DatagramPacket(sendData, sendData.length,iAddress);
socket.send(packet);
I think it has something to do with my network / setup.
When I reconnect to my wireless acces point, my app doesn't give this exception and I can see the package in my console:
MacBook-Pro-van-Roy:~ Roy$ sudo tcpdump -ni en1 host 239.255.255.250
Password:
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on en1, link-type EN10MB (Ethernet), capture size 65535 bytes
19:54:18.688367 IP 192.168.1.34.57428 > 239.255.255.250.1900: UDP, length 129
19:54:18.789447 IP 192.168.1.34.57428 > 239.255.255.250.1900: UDP, length 129
19:54:18.890506 IP 192.168.1.34.57428 > 239.255.255.250.1900: UDP, length 129

InetSocketAddress is not a InetAddress (it's a SocketAddress). You probably want something like this:
InetAddress addr = InetAddress.getByName("239.255.255.250");
packet = new DatagramPacket(sendData, sendData.length, addr, 1900);
socket.send(packet);

Related

Android UDP hole punching

I am trying to make an streaming app and I want to use UDP. I would like the connection to be P2P. So I have a java tcp server running on google cloud, an android phone and my pc. When android connects to tcp server it will create a DatagramSocket on the server that will receive the packet android sends to get the port and ip. Same for the pc. Each client will get the other's client ip and port and each client will get the port that the server received (EG: android sends from port 18000, it will get other's client ip and port and port 18000). Then I close the initial DatagramSocket and open a new one that is bound to the port it gets from server (in our eg 18000). But the connection is never created between the pc and android (android is on 4G and pc on router , so different networks)
socket = new DatagramSocket(Integer.parseInt(po));
Here is how I create the P2P datgram socket, where po is 18000 (each client has different po - the android has 18000 and the pc has let's say 45000), I get those port from tcp server and is ok.
public void send() throws NumberFormatException, IOException
{
//only for testing
byte[] buffer = new byte[1024];
buffer = "test".getBytes();
DatagramPacket packet = new DatagramPacket(buffer, buffer.length,InetAddress.getByName(ip),Integer.parseInt(port));
socket.send(packet);
}
Here is how i send data from the P2P datagram. The ip is the other's client public ip and the port is the other's client port that is listening.
#Override
public void run() {
// TODO Auto-generated method stub
while (true) {
byte[] buffer = new byte[64000];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
try {
socket.receive(packet);
//acum ca am primit
String ana = new String(packet.getData());
System.err.println("Am primit de la celalalt "+ana);
}
}
Here is the thread that listens for incoming packets.
The main problem is that this works but only when the client are on the same network as the server!Even if I both client are on the same netowk , but the server is on a different one, they won't receive anything. Data sent from TCP is 100% correct.
DatagramPacket packet= new DatagramPacket(buffer,buffer.length, InetAddress.getByName("server_ip"),port_main);
socket_udp.send(packet);
Here is how I send the UDP packet to the server in order to get the port back.
I tried using the same socket_udp ,without creating socket var again, it failed too.

How to bind java.net.MulticastSocket to localhost

I would like to bind a MulticastSocket to the address 127.0.0.1 (Socket should only be reachable within the current host) but with the following code example i got a
java.net.SocketException: Network is unreachable: Datagram send failed exception
Is there a way to fix the problem? Here is my code
int port = 6677;
InetAddress group = InetAddress.getByName("232.0.1.10");
try(MulticastSocket s = new MulticastSocket(new InetSocketAddress(InetAddress.getByName("127.0.0.1"),port))){
String msg = "Hello";
s.joinGroup(group);
DatagramPacket hi = new DatagramPacket(msg.getBytes(), msg.length(),group, port);
s.send(hi);
}
Multicast is a little odd when compared to traditional UDP communication. The whole point is to share data on a known "channel", simultaneously, to anyone who wants access. This sharing is "signaled" to the network by using an IP address in the range 224.0.0.1 to 239.255.255.255. If you try to bind to 127.0.0.1, you just aren't doing Multicast anymore. And if you take a minute and think about it, that makes sense - you can't share the internal interface with other computers.

Java UDP cant bind to local IP address(Ethernet)

My laptop is connected with ethernet cable and wifi
my ethernet ip: 192.168.18.32
my wifi ip: 192.168.18.167
Now I would like to send a udp packet through java using wifi network interface.
I read that if i bind to the correspoding ip then the corresponding interface will be used to send udp packet ie if i bind to ip 192.168.18.167 then udp packets will sent using wifi interface
my code is:
final String wiFiCardAddressName = "192.168.18.32";
final String ethernetAddressName = "192.168.18.167";
final InetAddress wiFiCardAddress = InetAddress.getByName(wiFiCardAddressName);
final InetAddress ethernetAddress = InetAddress.getByName(ethernetAddressName);
DatagramSocket datagramSocketWifi = new DatagramSocket(10000, wiFiCardAddress);
System.out.println(ethernetAddress);
DatagramSocket datagramSocketEt = new DatagramSocket(6666, ethernetAddress);
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, serverPort);
but whenever this send method is called
datagramSocketWifi.send(sendPacket);
datagramSocketet.send(sendPacket);
It shows the following error:
Exception in thread "main" java.net.BindException: Cannot assign requested address: Datagram send failed
at java.net.DualStackPlainDatagramSocketImpl.socketSend(Native Method)
at java.net.DualStackPlainDatagramSocketImpl.send(Unknown Source)
at java.net.DatagramSocket.send(Unknown Source)
at socket_test.Client_UDP_Bind.main(Client_UDP_Bind.java:50)
My server was running on localhost ie 127.0.0.1 when i moved my server to an external host ie IP then this same code worked. I could sent packets using ehternet or wife and could see the log in wireshark.

How to get local address of a DatagramSocket (UDP) in Java

I'm implementing a DNS server with DatagramSocket (UDP) in Java and the code looks like:
try (DatagramSocket socket = new DatagramSocket(new InetSocketAddress("0.0.0.0", 53))) {
DatagramPacket request = ... // Init Packet
socket.receive(request);
... // Parse request, Resolve, then Generate reesponse
socket.send(response);
}
It works fine on my PC and most servers (including aws, linode, etc), but does not work well on a server with double ethernet adapter.
This server has a network config:
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
address 192.168.1.204
netmask 255.255.255.0
auto eth1
iface eth1 inet static
address 192.168.1.207
netmask 255.255.255.0
When I test this DNS, I get:
# nslookup
> server 192.168.1.207
Default server: 192.168.1.207
Address: 192.168.1.207#53
> info.dev.
;; reply from unexpected source: 192.168.1.204#53, expected 192.168.1.207#53
;; reply from unexpected source: 192.168.1.204#53, expected 192.168.1.207#53
;; reply from unexpected source: 192.168.1.204#53, expected 192.168.1.207#53
;; connection timed out; no servers could be reached
>
It seems to receive a packet from eth1 (192.168.1.207) but send to eth0 (192.168.1.204). And my code does not know which interface the packet is received from.
try (DatagramSocket socket = new DatagramSocket(new InetSocketAddress("0.0.0.0", 53))) {
...
socket.receive(request); // local socket address not known :-(
...
socket.send(response); // local socket address not known :-(
}
Socket (TCP) can do this but I do not know whether DatagramSocket (UDP) can do so.
UPDATE-1:
bind one interface instead of 0.0.0.0, it works fine.
UPDATE-2:
Socket (TCP) can get both local and remote address:
try (ServerSocket server = new ServerSocket(23)) {
try (Socket socket = server.accept()) {
System.out.println(socket.getLocalSocketAddress());
System.out.println(socket.getRemoteSocketAddress());
}
}
The local address of that DatagramSocket is 0.0.0.0:53. The one you specified when you constructed it. Which interface it uses to reply on is determined by the static IP routing tables. Not by this code. And getting the local address of the DatagramSocket, or even the target address of the datagram (which you can get in C but not Java), wouldn't help you to solve this problem, if it is a problem.
my code does not know which interface the packet is received from.
Correct. It doesn't care. It is listening at all IP addresses. You told it to do that. It only cares about the remote address, which you haven't shown but have clearly got correct.
try (DatagramSocket socket = new DatagramSocket(new InetSocketAddress("0.0.0.0", 53))) {
I don't know why you've posted this twice.
What you have here is a static IP routing issue. Not a programming problem.

Java DatagramSocket sending but not receiving

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)

Categories

Resources