Learning java MulticastSocket, the same LAN only the machine can receive the broadcast, the other equipment can not. why? Is the router setting problem or the broadcast address setting problem?
send.java
public class sentServer {
public static void main(String[] args) {
String host = "224.0.0.1";
int port = 9998;String message = "test-multicastSocket";
try {
InetAddress group = InetAddress.getByName(host);
MulticastSocket s = new MulticastSocket();
s.joinGroup(group);
DatagramPacket dp = new DatagramPacket(message.getBytes(),message.length(),group,port);
s.send(dp);
s.close();
} catch (UnknownHostException e)
{
e.printStackTrace();
} catch (IOException e)
{e.printStackTrace();
}
}
}
The listening address set here is 224.0.0.1
recevier.java
public class reClinet {
public static void main(String[] args) {
String host="224.0.0.1";
int port=9998;
int length=1024;
byte[] buf=new byte[length];
MulticastSocket ms=null;
DatagramPacket dp=null;
StringBuffer sbuf=new StringBuffer();
try {
ms=new MulticastSocket(port);
dp=new DatagramPacket(buf,length);
InetAddress group=InetAddress.getByName(host);
ms.joinGroup(group);
System.out.println("port is open");
ms.receive(dp);
ms.close();
int i;
for(i=0;i<1024;i++){
if(buf[i]==0){
break;
}
sbuf.append((char)buf[i]);
}
System.out.println("message"+sbuf.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
`
Thanks
In case you are asking: why can only systems attached to the same network segment see broadcasts?
That is the nature of broadcasts in Java: a client connects to a specific server; and joins the broadcast group; then that client will be notified.
If a client doesn't get those notifications; you have to look into your network settings, firewalls, ...
Related
So my application is a very simple. If you type something through the scanner it sends it over to the server, the server sends it back to client. However, i don't understand why we have to put our code where we handle our receiving packets from the server into a thread?
The code below works fine but if i don't use use multithreading then the application doesn't work. The part where i send packets also stop working. Could you explain why this happens?
public class Client {
private static DatagramSocket socket = null;
public static void main(String[] args) {
System.out.println("Send to server:");
Scanner scanner = new Scanner(System.in);
while (true) {
try {
// port shoudn't be the same as in TCP but the port in the datagram packet must
// be the same!
socket = new DatagramSocket();
} catch (SocketException e1) {
System.out.println("[CLIENT] Unable to initiate DatagramSocket");
}
InetAddress ip = null;
try {
ip = InetAddress.getByName("127.0.0.1");
} catch (UnknownHostException e) {
System.out.println("[CLIENT] Unable to determine server IP");
}
// must be in a while loop so we can continuously send messages to server
String message = null;
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
receive();
}
});
thread.start();
while (scanner.hasNextLine()) {
message = scanner.nextLine();
byte[] buffer = message.getBytes();
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, ip, 6066);
try {
socket.send(packet);
} catch (IOException e) {
System.out.println("[CLIENT] Unable to send packet to server");
}
}
}
}
private static void receive() {
// receiving from server
byte[] buffer2 = new byte[100];
DatagramPacket ps = new DatagramPacket(buffer2, buffer2.length);
while (true) {
try {
socket.receive(ps);
} catch (IOException e) {
System.out.println("[CLIENT] Unable to receive packets from server.");
}
System.out.println("[SERVER] " + new String(ps.getData()));
}
}
}
If you type something through the scanner it sends it over to the
server, the server sends it back to client.
So the main method runs on the main thread and does some job. The job that you just referenced.
Read some user input plus the following part
while (scanner.hasNextLine()) {
message = scanner.nextLine();
byte[] buffer = message.getBytes();
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, ip, 6066);
try {
socket.send(packet);
} catch (IOException e) {
System.out.println("[CLIENT] Unable to send packet to server");
}
}
Title: receive packets from an UDP server
You want to receive packets but you don't want to block the user from typing something as input and sending it to the server.
Therefore you need to do 2 jobs simultaneously. AKA multithreading
I have to send UDP broadcast in Android.I am always getting java.io.IOException: Invalid argument at socket.send(packet).
When creating object of socket I sometimes get Address already in use Exception
My Code Complete code is (Edit 2) :
private void setBroadCastMessage() {
final int udpPortNumber = 6000;
ConnectivityManager connManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo mWifi = connManager.getActiveNetworkInfo();
if (mWifi.getType() == ConnectivityManager.TYPE_WIFI) {
if (mWifi.isConnected()) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
try {
InetAddress address;
address=InetAddress.getByName("255.255.255.255");
DatagramSocket datagramSocket = new DatagramSocket(udpPortNumber,address);
messageBroadCast(datagramSocket,address);
} catch (SocketException e) {
e.printStackTrace();
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
thread.start();
}
}
}
public void messageBroadCast(DatagramSocket socket, InetAddress address)
{
String data="This is my discovery request";
DatagramPacket packet = new DatagramPacket(data.getBytes(), data.length(),
address, 6000);
try {
socket.send(packet);
LogUtils.errorLog("Address :"," "+address);
LogUtils.errorLog("Send String:"," "+data);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Can't really post this as a comment but here is the code I have used which works and is extremely similar to yours.
Try this and add your stack trace to the question if you have further issues.
I use this to successfully broadcast to IP address "255.255.255.255"
private void sendToIP(String ip, int port, String message) {
try {
DatagramSocket socket = new DatagramSocket();
byte[] sendData = message.getBytes();
InetAddress IPAddress = InetAddress.getByName(ip);
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port);
socket.send(sendPacket);
} catch (Exception e) {
e.printStackTrace();
}
}
If you want to broadcast, you may need to call DatagramSocket.setBroadcast(true). But broadcast of the type you're attempting here has been deprecated for over 20 years.
I'm trying to create a simple multicast communication between my PC (Ubuntu, client) and my phone (Android, server).
Unicast/TCP connections work without any problem, the defined port (37659) opens both on PC and phone. When trying to use a MulticastSocket, no ports get opened. nmap tells me the specified port (36963) is a TCP port and that it is closed. (While the receive-method is being executed).
Am I doing something wrong? Or is the firewall blocking the multicast sockets? (I've tried about 20 different ports and none worked..., currently using port 36963)
EDIT: Also with the firewall completely down, nmap tells me the port is closed...
The server's code (phone):
private void multicastLoop() {
String res = Build.FINGERPRINT + "\n";
final InetAddress group;
final MulticastSocket socket;
final DatagramPacket response;
try {
group = InetAddress.getByName("224.0.0.115");
socket = new MulticastSocket(mport);
socket.setLoopbackMode(true);
socket.setSoTimeout(10000);
socket.joinGroup(group);
response = new DatagramPacket(res.getBytes(), res.length(), group, mport);
} catch (IOException e) {
e.printStackTrace();
return;
}
Thread t = new Thread(new Runnable() {
#Override
public void run() {
while(isRunning) {
try {
byte[] data = new byte[1024];
DatagramPacket dm = new DatagramPacket(data, data.length);
socket.receive(dm);
Log.d("udp", "received");
if (Arrays.equals(dm.getData(), "someone there".getBytes())) {
socket.send(response);
}
} catch (SocketTimeoutException e) {
continue;
} catch (IOException e) {
e.printStackTrace();
}
}
try {
socket.leaveGroup(group);
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
t.start();
}
The client's code (computer):
public String[] findServers() {
String hello = "someone there";
try {
InetAddress group = InetAddress.getByName(mhost);
MulticastSocket socket = new MulticastSocket(mport);
socket.setLoopbackMode(true);
socket.setSoTimeout(60000);
socket.joinGroup(group);
DatagramPacket p = new DatagramPacket(hello.getBytes(), hello.length(), group, mport);
byte[] buffer = new byte[1024];
socket.send(p);
DatagramPacket r = new DatagramPacket(buffer, buffer.length);
socket.receive(r);
socket.leaveGroup(group);
socket.close();
String srinfo = "";
byte[] data = r.getData();
for (byte b: data)
srinfo += (char) b;
System.out.println("Server found at " + r.getAddress().getHostName() + ": " + srinfo);
} catch (SocketTimeoutException e) {
return new String[] {"timeout"};
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
Make sure mhost is set to "224.0.0.115" not some machine name.
Make sure multicast is enabled on your router.
If the host is multi-homed, you need to join the multicast group via all local interfaces, not just the default one, which is what you're doing at present.
You could send the response back to the source address it came from, which is in the received datagram packet. That would also mean that the client doesn't need a MulticastSocket, only a DatagramSocket.
Im trying to write server and client for service which would tell the current time. My code:
SERVER
public class TimeServer {
public static void main(String[] args) {
try {
final DatagramSocket so = new DatagramSocket(8189);
new Thread(new Runnable() {
#Override
public void run() {
try {
while (true) {
try {
InetAddress group = InetAddress.getByName("200.20.2.0");
byte[] buf = new byte[256];
Calendar cal = Calendar.getInstance();
buf = cal.toString().getBytes();
DatagramPacket packet = new DatagramPacket(buf, buf.length,
group, 8189);
so.send(packet);
} catch (IOException ex) {
ex.printStackTrace();
}
Thread.sleep((int)(Math.random() * 5));
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}).start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
CLIENT
public class TimeClient {
public static void main(String[] args) {
try {
MulticastSocket so = new MulticastSocket(8190);
InetAddress group = InetAddress.getByName("200.20.2.0");
so.joinGroup(group);
//5 razy czekamy na otrzymanie od serwera wiadomosci
for (int a=0; a<5; a++) {
byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
so.receive(packet);
String recv = new String(packet.getData());
System.out.println("RECEIVED: " + recv);
}
so.leaveGroup(group);
so.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
When launching server and then client I get the following error:
java.net.BindException: Address already in use
at java.net.PlainDatagramSocketImpl.bind0(Native Method)
at java.net.AbstractPlainDatagramSocketImpl.bind(AbstractPlainDatagramSocketImpl.java:95)
at java.net.DatagramSocket.bind(DatagramSocket.java:376)
at java.net.MulticastSocket.<init>(MulticastSocket.java:172)
at java.net.MulticastSocket.<init>(MulticastSocket.java:137)
at timeclient.TimeClient.main(TimeClient.java:13)
Please help, thanks
EDIT:
I changed client port and now I get exception:
java.net.SocketException: Not a multicast address
at java.net.MulticastSocket.joinGroup(MulticastSocket.java:306)
at timeclient.TimeClient.main(TimeClient.java:15)
What's now?
Every Port can only be used by a single application. In your case, your server and your client (2 applications) are trying to use the same port which is causing the exception.
To fix it, change for example the port for the client from 8189 to 8190
You must change the client port (or the server port) because every port only can be used by a single process.
try DatagramSocket.setReuseAddress(true) and see what happens.
I have a very similar behaviour as described here:
running on a Mac Book Pro, Snow Leopard
using Multicast Sockets to send and receive packets on localhost
I'm using Eclipse and observed the following behaviour when the client / server are started from within the workspace:
if the wireless interface (airport) is up and running, the client does not receive any packets
if the interface is turned off, everything works as expected
But what I don't understand is:
if I create a JAR and run the code in any console -> all good! Just Eclipse seems not to like airport ;-)
depending on what wireless network I'm connected to, the above behaviour might change, i.e. it also works if airport is enabled (for example # Uni)
Does anyone have an idea 'bout this?
Cheers
Below the straightforward code for server / client:
#Override
public void run() {
String multicastAddress = "224.0.0.2";
int multicastPort = 8000;
MulticastSocket socket = null;
try {
try {
InetAddress multicastGoup = InetAddress.getByName(multicastAddress);
socket = new MulticastSocket(multicastPort);
socket.joinGroup(multicastGoup);
} catch (IOException e) {
e.printStackTrace();
return;
}
byte[] buffer = new byte[1024];
while (true) {
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
System.out.println("BEFORE RECEIVE: listening on " + multicastAddress + ":" + multicastPort);
socket.receive(packet);
System.out.println("PACKET RECEIVED");
System.err.println("Client received: " + new String(packet.getData()));
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
socket.close();
}
}
Server:
public void run() {
MulticastSocket socket = null;
try {
String multicastAddress = "224.0.0.2";
int multicastPort = 8000;
InetAddress multicastGoup = InetAddress.getByName(multicastAddress );
socket = new MulticastSocket(multicastPort);
socket.joinGroup(multicastGoup);
byte[] data = new String("Teststring").getBytes();
while (true) {
socket.send(new DatagramPacket(data, data.length, multicastGoup, multicastPort));
System.out.println("SERVER: Datagram sent");
Thread.sleep(1000);
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
socket.close();
}
}
From Class MulticastSocket:
void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
Joins the specified multicast group at the specified interface.
Try using a specific interface so your joinGroup doesn't fall into the default - which may vary according on available, open ones or due to Eclipse settings.
joinGroup
public void joinGroup(SocketAddress mcastaddr,
NetworkInterface netIf)
throws IOException
Joins the specified multicast group at the specified interface.
If there is a security manager, this method first calls its
checkMulticast method with the mcastaddr argument as its argument.
Parameters:
mcastaddr - is the multicast address to join
netIf - specifies the local interface to receive
multicast datagram packets,
-- here is the catch
or null to defer to the interface set by
setInterface(InetAddress) or
setNetworkInterface(NetworkInterface)