I have a Multicast socket open and is receiving Multicast message. From this thread, it seems that the same multicast socket should also be able to receive unicast messages. However, I'm not able to get anything.
Edit: the port number seems the be problem. Port 3702 is used by ws-discovery for unicasting which is related to what I'm trying to do. I'm tracking down a problem where the client's probe to the service is not caught by the service's multicast socket. I'm running this on windows.
My multicast server:
class Server extends Thread {
MulticastSocket multicastSocket;
final Logger LOG;
final int PORT = 3702;
final String MULTICAST_ADDR = "239.255.255.250";
InetAddress multicastGroup;
public Server() {
LOG = Logger.getLogger("Server");
try {
multicastGroup = InetAddress.getByName(MULTICAST_ADDR);
multicastSocket = new MulticastSocket(PORT);
multicastSocket.setInterface(InetAddress.getLocalHost());
multicastSocket.joinGroup(multicastGroup);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
while (!Global.exit) {
byte[] buf = new byte[1000];
DatagramPacket recv = new DatagramPacket(buf, buf.length);
try {
multicastSocket.receive(recv);
String msg = new String(recv.getData(), StandardCharsets.UTF_8);
LOG.log(Level.INFO, "got: " + msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
And the client code:
public void directMsgTest(){
try {
DatagramSocket datagramSocket = new DatagramSocket( 8080,InetAddress.getLocalHost());
String msg = "direct msg";
byte[] buf = msg.getBytes();
DatagramPacket packet = new DatagramPacket(buf, buf.length, InetAddress.getLocalHost(), DST_PORT);
datagramSocket.send(packet);
datagramSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
It seems that this is Window's fault. It uses WS discovery in some of its services, thus using port 3702 and eating unicast packets send to port 3702 instead of giving it to my server.
I tried running this on Linux and it was fine.
Related
I created a chat application to sent messages to a multicast group conversation with multiple clients.
The message has to been send to the MulticastServer and sent to all client on Multicast Group. At this point, the message arrive at the server from client in perfect conditions.
But when i reply back to client (even a simple String), the message is sending only to the client that send the message and not for all users in the Multicast Group.
The StackTrace doesn't give me any error, but i still getting this issue.
I give you some of the important code. The following one refering the connection to multicast server. The DEFAULT_ADRESS is 224.0.0.3.
socket = new MulticastSocket();
address = InetAddress.getByName(DEFAULT_ADRESS);
socket.joinGroup(address);
The part of the code that send a message to MulticastServer:
String messtoSendServer = utilizadorOnline.getNome() + ":" + textfieldtocomunicateGroupe.getText();
buf = messtoSendServer.getBytes();
packet = new DatagramPacket(buf, buf.length, address, DEFAULT_PORT);
try {
// userOnline_Multicast.getSocketMulti().send(packet);
socket.send(packet);
} catch (IOException ex) {
Logger.getLogger(ConversaGrupo.class.getName()).log(Level.SEVERE, null, ex);
}
The part of the code that receive the message from server:
private void receberDadosServidor() throws IOException {
try {
DatagramPacket packet1 = new DatagramPacket(buf, buf.length);
socket.receive(packet1);
String received = new String(packet1.getData());
textareatoGroupChat.setText(textareatoGroupChat.getText() + "\n" + received);
} catch (IOException ex) {
Logger.getLogger(ConversaGrupo.class.getName()).log(Level.SEVERE, null, ex);
socket.close();
socket.leaveGroup(address);
}
This is the Server Side. First start the Thread:
public void run(JTextArea txtArea) throws IOException {
new MulticastServerThread(txtArea).start();
}
And the Thread herself:
public class MulticastServerThread extends Thread {
private final String DEFAULT_MULTICASTIP = "224.0.0.3";
private final int DEFAULT_MULTICASTPORT = 4446;
private final int FIVE_SECONDS =5000;
private DatagramPacket packet;
private JTextArea textA;
private boolean moreQuotes = true;
private MulticastSocket socket = null;
private InetAddress adresstoConnectMulticast = null;
public MulticastServerThread(JTextArea txt) throws IOException {
super("MulticastServerThread");
this.textA = txt;
}
#Override
public void run() {
while (true) {
try {
byte[] buf = new byte[1024];
socket = new MulticastSocket(DEFAULT_MULTICASTPORT);
adresstoConnectMulticast = InetAddress.getByName(DEFAULT_MULTICASTIP);
socket.joinGroup(adresstoConnectMulticast);
packet = new DatagramPacket(buf, buf.length, adresstoConnectMulticast, DEFAULT_MULTICASTPORT); //usado para receber um datagram do socket, o array de bytes contem dados do cliente especifico
socket.receive(packet);
String mensagem = new String(packet.getData()).trim();
textA.setText(textA.getText() + "\n\nServer Multicast Receive from User:" + mensagem +" on IP Multicast " +DEFAULT_MULTICASTIP +" | "+ DEFAULT_MULTICASTPORT);
buf = mensagem.getBytes();
InetAddress ed = packet.getAddress();
int portad = packet.getPort();
//manda de volta para o cliente.
packet = new DatagramPacket(buf, buf.length, ed, portad);
socket.send(packet);
try {
sleep((long) Math.random() * FIVE_SECONDS);
} catch (InterruptedException e) {
}
} catch (IOException ex) {
Logger.getLogger(MulticastServerThread.class.getName()).log(Level.SEVERE, null, ex);
socket.close();
}
}
}
}
There are several problems here.
socket = new MulticastSocket();
Your clients all need to be bound to the same port. Provide a fixed port number to the constructor. Otherwise you get a system-allocated port.
Second, your server replies to the source's IP address and port number. It should reply to the group IP address and the source's port number, or the fixed port number above, which should be the same.
Third, 224.0.0.3 is reserved. You can't use it.
And leave the server's socket open. Don't open and close it every time around the loop.
I have an Android client and plain Java server both on the same subnet and I am sending UDP broadcast packets from client to server. With some routers (Netgear, Cisco) the server happily receives the packets, but for my Asus router while the server machine receives the packets the server DatagramSocket doesn't.
NB In all cases, Wireshark shows that the packets are getting to the server machine. But when using the Asus router the DatagramSocket doesn't seem to see them. To keep things simple the server only has an ethernet connection to the router.
The code is pretty standard.
Client:
DatagramSocket socket = null;
try {
socket = new DatagramSocket();
socket.setSoTimeout(500); // 500 millis
while (isRunning()) {
final InetAddress broadcastAddress = getSubnetBroadcastAddress();
final DatagramPacket outboundPacket = new DatagramPacket(REQUEST_MESSAGE, REQUEST_MESSAGE.length, broadcastAddress, broadcastPort);
socket.send(outboundPacket);
}
} catch (IOException e) {
Log.i(TAG, "Beacon failed", e);
} finally {
if (socket != null) {
socket.close();
}
}
private InetAddress getSubnetBroadcastAddress() throws IOException {
final WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
final DhcpInfo dhcp = wifi.getDhcpInfo();
if (dhcp == null) {
// No successful DHCP request. Go with best effort.
Log.d(TAG, "#getBroadcastAddress - No DHCP info so using generic broadcast address");
return InetAddress.getByName("255.255.255.255");
}
final int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask;
final byte[] quads = new byte[4];
for (int k = 0; k < 4; k++) {
quads[k] = (byte) ((broadcast >> k * 8) & 0xFF);
}
return InetAddress.getByAddress(quads);
}
Server:
DatagramSocket socket = null;
try {
socket = new DatagramSocket(broadcastPort);
socket.setSoTimeout(LISTENING_TIMEOUT);
socket.setBroadcast(true);
while (keepRunning) {
try {
final byte[] buffer = new byte[1024];
final DatagramPacket receivedPacket = new DatagramPacket(buffer, buffer.length);
socket.receive(receivedPacket);
log.debug("Received packet : " + receivedPacket.toString());
} catch (SocketTimeoutException e) {
log.debug("#run BeaconRunnable socket timed out");
}
}
} catch (IOException e) {
log.warn("Error while receiving message", e);
if (socket != null) {
socket.close();
}
}
What's causing the DatagramSocket to not see the UDP broadcast packets with the Asus router?
For those that follow ..
There is nothing wrong with the code above.
There was nothing wrong with the router config.
A rule had been added to Windows Firewall that blocked incoming UDP from public connections and the Asus router for some reason was deemed to be a public connection.
Disabling that rule let everything work.
I am currently exploring UDP packet transmission in Java to create a multiplayer game on Android.
I succeeded at exchanging packets within my Nexus 4 by using the usual "127.0.0.1" and I also succeeded at exchanging packets between my PC server and my Android client in my local network.
But since I will want my game to be playable on the Internet, I want my Android client to be able to exchange packets with my PC server when they aren't on the same local network. This is where I am struggling.
My setup : A PC server connected with my home Internet connection and a Nexus 4 connected with a 3G network.
First, my PC server starts listening on the port 10000 and my Android client opens a socket to receive server's packets on port 10001. Then, the Android client sends a packet to the PC server to its current public address "173.246.12.125" on port 10000. The PC server receives the packet and sends a response to the sender on port 10001. But the Android client never receives the response.
Here is my PC server code :
public class UDPServer {
private final static int SERVER_PORT = 10000;
private final static int CLIENT_PORT = 10001;
public static void main(String[] args) {
InetAddress clientAddr = null;
DatagramSocket socket = null;
try {
//Initializing the UDP server
System.out.println(String.format("Connecting on %s...", SERVER_PORT));
socket = new DatagramSocket(SERVER_PORT);
System.out.println("Connected.");
System.out.println("====================");
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (SocketException e) {
e.printStackTrace();
}
while(true){
try {
//Listening
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
System.out.println("Listening...");
socket.receive(packet);
//Getting client address from the packet we received
clientAddr = packet.getAddress();
System.out.println("Received: '" + new String(packet.getData()).trim() + "' from "+clientAddr.toString());
//Sending response
byte[] message = ("Hello Android").getBytes();
DatagramPacket response = new DatagramPacket(message, message.length, clientAddr, CLIENT_PORT);
DatagramSocket clientSocket = new DatagramSocket();
System.out.println("Sending: '" + new String(message) + "'");
clientSocket.send(response);
System.out.println("Response sent.");
System.out.println("--------------------");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
And here are my Android client classes :
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Receiver()).start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(new Client()).start();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
public class Receiver implements Runnable {
private final static int LISTENING_PORT = 10001;
#Override
public void run() {
try {
//Opening listening socket
Log.d("UDP Receiver", "Opening listening socket on port "+LISTENING_PORT+"...");
DatagramSocket socket = new DatagramSocket(LISTENING_PORT);
socket.setBroadcast(true);
socket.setReuseAddress(true);
while(true){
//Listening on socket
Log.d("UDP Receiver", "Listening...");
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
Log.d("UDP", "Received: '" + new String(packet.getData()).trim() + "'");
}
} catch (Exception e) {
Log.e("UDP", "Receiver error", e);
}
}
}
public class Client implements Runnable {
private final static String SERVER_ADDRESS = "173.246.12.125";//public ip of my server
private final static int SERVER_PORT = 10000;
#Override
public void run() {
try {
//Preparing the socket
InetAddress serverAddr = InetAddress.getByName(SERVER_ADDRESS);
DatagramSocket socket = new DatagramSocket();
//Preparing the packet
byte[] buf = ("Hello computer").getBytes();
DatagramPacket packet = new DatagramPacket(buf, buf.length, serverAddr, SERVER_PORT);
//Sending the packet
Log.d("UDP", String.format("Sending: '%s' to %s:%s", new String(buf), SERVER_ADDRESS, SERVER_PORT));
socket.send(packet);
Log.d("UDP", "Packet sent.");
} catch (Exception e) {
Log.e("UDP", "Client error", e);
}
}
}
The server's console is showing the IP of the client :
Connecting on 192.168.1.126:10000...
Connected.
====================
Listening...
Received: 'Hello computer' from /204.48.72.68
Sending: 'Hello Android'
Response sent.
--------------------
Listening...
The packet seems to come from the address 204.48.72.68, but if I go on whatismyip.com on my Android, it shows me 96.22.246.97... I don't know where 204.48.72.68 is coming from...
I am not sure if the problem is that my listening socket on my Android client is not good or if the PC server does not send the response to the correct address.
Could someone points me what am I doing wrong?
Thank you
I came across a similar issue, but I was using TCP Sockets instead of UDP. My intense was sending files directly to a mobile. In LAN this worked pretty much.
It appears, that's not possible to send data to listening sockets, when your phone is connected to internet using the mobile connection.
I've read on some pages (sry dont have any links anymore), that incoming connections on a mobile phone is blocked by the telecommunications provider.
My workaround was to create outgoing connections to the server and use the bidirectional possiblities of tcp sockets.
Maybe you can use your "working" datagram socket, to exchange data with your mobile.
Here is an example, which i had found:
http://itucet.blogspot.de/2011/03/java-bidirectional-data-transfer-using.html
Same code working well for me, Have an issue when tried with emulator but its works fine if you use any android mobile .
The reason for the issue is android emulator and your computer are not in same subnet .
I'm having some problems receiving a String from a multicast.
It's the first time i'm using UDP multicast in Java.
I'm making a multiclient application over a LAN.
So i'm using Local Ip addresses.
I need the clients to find the server's IP address so they can send their data, requests, etc.
I let the server sent out a multicast with his own IP as a string every 5 seconds.
The clients should be able to receive it.
The problem is that they don't receive anything.
I'm testing with 2 devices so i don't need to use localhost.
Here's some of my code:
Server side:
public class MulticastIpSender extends Thread{
private String serverIp;
private int port;
private String multicastAddress;
private long WAITING_TIME = 5000; // 5 seconden
private DatagramSocket socket;
public MulticastIpSender(String serverIp, int port, String multicastAddress) throws SocketException {
super();
this.serverIp = serverIp;
this.port = port;
this.multicastAddress = multicastAddress;
socket = new DatagramSocket(port);
}
public void run() {
while(true){
try {
byte[] buf = new byte[256];
buf = serverIp.getBytes();
InetAddress group = InetAddress.getByName(multicastAddress);
DatagramPacket packet = new DatagramPacket(buf, buf.length, group, port);
socket.send(packet);
System.out.println("sent IP("+serverIp+") to group("+group+") on port "+port);
sleep(WAITING_TIME);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
I put this method in the main class:
private void sendIpAddressToListeners() {
try {
multicastIpSender = new MulticastIpSender(serverIp,PORT,"230.0.0.1");
multicastIpSender.run();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I get the serverIp like this:
String hostName = InetAddress.getLocalHost().getHostName();
InetAddress addrs[] = InetAddress.getAllByName(hostName);
if (!addr.isLoopbackAddress() && addr.isSiteLocalAddress()) {
myIp = addr.getHostAddress();
}
}
System.out.println ("\nIP = " + myIp);
return myIp;
on this device it gives me 192.168.1.2
CLIENT SIDE:
multicastSocket = new MulticastSocket(PORT);
InetAddress address = InetAddress.getByName(MULTICAST_ADDRESS);
multicastSocket.joinGroup(address);
DatagramPacket serverIpPacket;
byte[] buf = new byte[256];
serverIpPacket = new DatagramPacket(buf, buf.length);
while(receivedIp ==null){
multicastSocket.receive(serverIpPacket);
receivedIp = new String(serverIpPacket.getData(), 0, serverIpPacket.getLength());
System.out.println("received server ip: " + receivedIp);
}
!! PORT = 4445 in both server and client
I hope somebody can help me with this or can explain a better way to do this.
Send a normal DatagramPacket on broadcast address, the packet will be received by all hosts in local network (with same network configuration, important part is mask)
Use calculator to check your broadcast address, this one works good: http://www.subnet-calculator.com/
my android device is connected to my home-wireless-network. Also a special UDP-device is connected to it. My android app successfully can send commands to the UDP-device. But if I open a socket it does not receive data. Can you see what is wrong? I know the ip of the UDP-device from the iphone-APP which is working
Here is how the app send commands:
public static final String SERVERIP = "192.168.2.114";
public static final int PORT = 44444;
public void run() {
try {
serverAddr = InetAddress.getByName(SERVERIP);
DatagramSocket socket = new DatagramSocket();
byte[] buf = message.toByteArray();
DatagramPacket packet = new DatagramPacket(buf, buf.length, serverAddr, PORT);
socket.send(packet);
socket.close();
} catch (Exception e) {
Log.e("UDP", "Sender/Client: Error", e);
}
}
Whereas I have two approaches for receiving data:
public static final String SERVERIP = "192.168.2.114";
public static final int SERVERPORT = 44445;
private InetAddress serverAddr;
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(SERVERIP);
DatagramSocket socket = new DatagramSocket(SERVERPORT, serverAddr);
byte[] buf = new byte[65213];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
} catch (Exception e) {
Log.e("UDP", "Receiver: Error", e);
}
try {
serverAddr = InetAddress.getByName(SERVERIP);
DatagramChannel channel = DatagramChannel.open();
DatagramSocket socket = channel.socket();
byte[] buf = new byte[65213];
DatagramPacket packet = new DatagramPacket(buf, buf.length, serverAddr, SERVERPORT);
socket.receive(packet);
socket.close();
} catch (Exception e) {
Log.e("UDP", "Sender/Client: Error", e);
}
}
The approach in the first try block leads to an exception:
java.net.BindException: Cannot assign requested address
at org.apache.harmony.luni.platform.OSNetworkSystem.bind(Native Method)
at dalvik.system.BlockGuard$WrappedNetworkSystem.bind(BlockGuard.java:268)
at org.apache.harmony.luni.net.PlainDatagramSocketImpl.bind(PlainDatagramSocketImpl.java:81)
at java.net.DatagramSocket.createSocket(DatagramSocket.java:193)
at java.net.DatagramSocket.<init>(DatagramSocket.java:95)
at de.myappname.connection.Receiver.run(Receiver.java:29)
at java.lang.Thread.run(Thread.java:1019)
The second approach just blocks the thread by socket.receive(packet) which does not receive data. From the iphone and specification I know the device sends data via UDP 44445 over WLAN. Any suggestions what is wrong?
Thank you!
UDP port 44445 is used by eMule protocol. Do you have any other eMule clients active on your device?
Update:
The problem seems to be the address you bind to - it must be an address on the localhost, i.e. IP address of your device, not remote device. See DatagramSocket(port, InetAddress) constructor.
I guess you need to put the receive() function inside a while loop since you current code looks like it receives message only once; it doesn't guarantee that it will contain any valid data.