I have 2 UDP broadcast servers at 192.168.1.1 broadcasting to 192.168.1.255:1234 and at 192.168.2.1 broadcasting to 192.168.2.255:1235.
I have a client that must receive all packets.
here is a simple code in java:
final DatagramSocket socket1, socket2;
socket1 = new DatagramSocket(1234);
socket2 = new DatagramSocket(1235);
final DatagramPacket p = new DatagramPacket(new byte[10], 10);
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
socket1.receive(p);
System.out.println(p.getAddress());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
socket2.receive(p);
System.out.println();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
}
The problem is that the java application cannot receive from both NICs in Ubuntu. It always receives from 192.168.2.255 (eth1). All packets can be dumped using wireshark, but java cannot receive them.
Also when I use exactly the same java code in TinyCore distro, there is no problem receiving packets from both NICs.
What's wrong with Java in Ubuntu?
If you want to bind to a specific address, you need to specify it:
socket1 = new DatagramSocket(1234, InetAddress.getByName("192.168.1.255"));
socket2 = new DatagramSocket(1235, InetAddress.getByName("192.168.2.255"));
Also, you shouldn't use the same DatagramPacket instance in both threads as the will definitely share the buffer, and in case of concurrent packets, the outcome is unpredictable.
Related
I have a server app written in C# for Windows. I have a client app for android. I want to send data continuously from client to server in an infinite loop. The data is being sent but sometimes, there is a bad delay. I'm really stuck at it. Here's my client side code:
new Thread(new Runnable() {
public void run() {
Socket socket = null;
PrintWriter out = null;
while(true) {
try {
socket = new Socket(IP, PORT);
out = new PrintWriter(socket.getOutputStream(), true);
out.println(msg);
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
Any idea why is there a delay?
Your problem is that you are initializing the socket every single iteration of your while loop.
new Thread(new Runnable() {
public void run() {
Socket socket = null;
PrintWriter out = null;
while(true) {
try {
socket = new Socket(IP, PORT);
out = new PrintWriter(socket.getOutputStream(), true);
out.println(msg);
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
Refactor it out of the loop, like this:
new Thread(new Runnable() {
public void run() {
Socket socket = new Socket(IP, PORT);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
while(true) {
try {
out.println(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
}).start();
Unless that is by design, in which case, why?
It seems the code is correct. The lag may be caused not only by the application but also by the network status.
Try to ping to the router from both devices and see if you are having lag spikes due to the wireless conection. If you see high lag in pings the problem is in the connection, not in the application.
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.
On a single port I want to listen for Multicast, UDP, and TCP traffic. (on my LAN)
I also want to respond via UDP, if something is detected.
The code works below, but only for Multicast detection. The while(true) loop is definitely doing it just, from the main().
But I'm running into a wall with adding another protocol detection method.
Can a single application have multiple sockets open, in multiple protocols?
I'm sure it's my limited knowledge of threading, but maybe someone can see my hiccup below.
public class LANPortSniffer {
private static void autoSendResponse() throws IOException {
String sentenceToSend = "I've detected your traffic";
int PortNum = 1234;
DatagramSocket clientSocket = new DatagramSocket();
InetAddress IPAddress = InetAddress.getByName("192.168.1.121");
byte[] sendData = new byte[1024];
sendData = sentenceToSend.getBytes();
DatagramPacket sendPacket =
new DatagramPacket(sendData, sendData.length, IPAddress, PortNum);
clientSocket.send(sendPacket);
clientSocket.close();
}//eof autoSendResponse
private static void MulticastListener() throws UnknownHostException {
final InetAddress group = InetAddress.getByName("224.0.0.0");
final int port = 1234;
try {
System.out.println("multi-cast listener is started......");
MulticastSocket socket = new MulticastSocket(port);
socket.setInterface(InetAddress.getLocalHost());
socket.joinGroup(group);
byte[] buffer = new byte[10*1024];
DatagramPacket data = new DatagramPacket(buffer, buffer.length);
while (true) {
socket.receive(data);
// auto-send response
autoSendResponse();
}
} catch (IOException e) {
System.out.println(e.toString());
}
}//eof MulticastListener
// this method is not even getting launched
private static void UDPListener() throws Exception {
DatagramSocket serverSocket = new DatagramSocket(1234);
byte[] receiveData = new byte[1024];
System.out.println("UDP listener is started......");
while(true)
{
DatagramPacket receivePacket =
new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
String sentence = new String( receivePacket.getData());
System.out.println("UDP RECEIVED: " + sentence);
}
}
public static void main(String[] args) throws Exception {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
try {
MulticastListener();
} catch (UnknownHostException e) {
e.printStackTrace();
}
// this does not appear to be detected:
try {
UDPListener();
} catch (Exception e) {
e.printStackTrace();
}
}
}//eof LANPortSniffer
In main(), I tried adding a second try/catch, for a simple UDPListener() method.
But it seems to be ignored when I run the application in Eclipse.
Does the main() method only allow for one try/catch?
In a nutshell, I'd like to listen on a single port for Multicast, UDP, and TCP packets all at the same time. Is this possible?
Your getting into a Threading issue here. I think you need to brush up on understanding of Java. When you call MulticastListener() it will never leave that block until your connection fails. It has a continous while loop. You need to create a new Thread for each of these activities.
Thread t = new Thread(new Runnable() {
public void run() {
MulticastListener();
}
}
t.start();
However I recommend you read up on your understanding of the programs flow and use of a more object orientated approach before you start trying to implement a threaded program.
1) You'll need raw socket access, which you won't get with a MulticastListener.
2) Look-up Promiscuous Mode and Raw Sockets in Java.
3) Threading issues are irrelevant - they will only give you better reactive performance - suggest you get it working with one thread before you improve your code.
So, i have a Android-App(Client) and a Java-program(Server), with a One-time socket communication, whenever the android app connects to my server in a special activity (working fine).
Because my server is embedded in a bigger program (with Swing-components, where the server takes its informations from), i have this (reduced) code here:
//somewhere in my Swing-Application
Server myServer = new Server();
myServer.start();
//...
public class Server extends Thread {
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(8090);
try {
while (true) {
System.out.println("Server is waiting for connections...");
socket = serverSocket.accept();
startHandler(socket);
}
} finally {
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void startHandler(final Socket socket) throws IOException {
System.out.println("Client connected to Server");
Thread thread = new Thread() {
#Override
public void run() {
try {
writer = new OutputStreamWriter(socket.getOutputStream(), "UTF-8");
//doing something usefull, i am sending a JSON-String, which i´ll parse in my app.
writer.write(someStringContainingJSONString);
writer.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
closeSocket();
}
}
private void closeSocket() {
try {
socket.close();
} catch (IOException e) {
}
}
};
thread.start();
}
In my Android-App i have:
public void onCreate(Bundle savedInstanceState) {
viewJSON = new Runnable() {
#Override
public void run() {
getJSON();
}
};
Thread thread = new Thread(null, viewJSON, "MagentoBackground");
thread.start();
myProgressDialog = ProgressDialog.show(myActivity.this, "Please wait...", "Retrieving data ...", true);
}
private void getJSON() {
try {
socket = new Socket(serverIPAddress, SERVER_PORT);
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
String help = reader.readLine();
// parse this String according to JSON, is working fine!
}
// catch and so on...
Now, i want the app, to recieve data, whenever i hit a button "send data" from my Swing-Application, to have the newest data available.
On the other hand, i want the server to recieve data (also a JSON-String) when i make changes in my Android app. The String should also be send when i hit a specific button.
How can i do that? The problem is the threading issue(otherwise my swing application wouldn´t work) combined with networking. If i don´t close the socket, i cannot continue with my program properly (or at least, it seems so with my code right now)
Can you help me out here?
Thank you very much in advance for your help and thoughts.
Best, Andrea
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)