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.
Related
So in my code below i have a singlethreaded server and a multithreaded client. The reason for this is because i want the client to send packets and receive packets simultaneously. However when i start the server and run multiple clients the server can process multiple clients simultaneously even tough the server is not multithreaded? Can you explain this?
Server:
public class server {
public static void main(String[] args) throws IOException{
new server();
}
//declare the UDP server socket
DatagramSocket datagramSocket;
int port = 3741;
public server() throws IOException {
//create UDP server with a specific port number
datagramSocket = new DatagramSocket(port);
System.out.println("[UDP server] Datagram socket started on port " + port);
//prepare the packet structure for received packets
int dataLength = 100; //must be large enough so some part of packet doesn't get lost
byte[] receiveData = new byte[dataLength];
DatagramPacket packet = new DatagramPacket(receiveData, receiveData.length);
while(true) {
datagramSocket.receive(packet);
System.out.println("client connected");
InetAddress inetAddress = packet.getAddress();
int clientPort = packet.getPort();
byte[] data = packet.getData();
//send response back to the client host
byte[] sendData = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(data, data.length, inetAddress, clientPort);
datagramSocket.send(datagramPacket); //sending data from server to client
}
}
}
Client:
public class client {
public static void main(String[] args) throws Exception {
new client();
}
public client() throws Exception{
DatagramSocket socket = new DatagramSocket();
InetAddress ip = InetAddress.getByName("127.0.0.1");
String message = "hello from client";
DatagramPacket packetSend = new DatagramPacket(message.getBytes(), message.getBytes().length, ip, 3741);
Thread th = new Thread(new Runnable() {
#Override
public void run() {
for(int i = 0; i < 100; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
socket.send(packetSend);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
th.start();
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
//this part can't be in a thread because the loop above us will finish first before this starts
//we can put this code before the loop and start a thread this would also work
while(true) {
try {
socket.receive(packet);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String data = new String(packet.getData()).trim();
System.out.println(data);
}
}
}
You think "the server can process multiple clients simultaneously even tough the server is not multithreaded" cause your brain cheat you. Acutually they are processing one by one in a reliatively fast speed. It's easy to see if you use wireshark or tcpdump to capture the server side packets. You will find the interesing truth.
I need two java applications to communicate across two computers. One is a front-end displaying information and taking user inputs, the other is a server storing it at the end of a session. The server also has an interface to add/remove users from the system.
I've gotten each application to work on their own, and I've gotten the communication set up to work on its own as well.
Now that I have to combine the modules I've run into an issue I can't seem to solve.
The "server" part of the communication is running in a while(true) loop waiting for packages. This makes it a bit hard to integrate it into the other applications.
I've been reading about Threads, thinking I'd "just" do that, but the complexity has me a bit baffled at the moment so I was hoping someone here could help me get going.
Here's the code in the Server class.
private String[] str = new String[4];
private String sentence;
private InetAddress IPAddress;
private int port;
private byte[] receiveData = new byte[1024];
private byte[] sendData = new byte[1024];
private DatagramSocket serverSocket;
private void listen(int serverPort) {
try {
this.serverSocket = new DatagramSocket(serverPort);
while (true) {
receivePackage();
splitPackage(this.sentence);
sendConfirm();
}
} catch (SocketException ex) {
System.out.println("UDP Port" + serverPort + "is unavailable.");
System.exit(1);
}
}
private void sendConfirm() {
this.sendData= "RECEIVED".getBytes();
DatagramPacket sendPacket = new DatagramPacket(this.sendData, this.sendData.length, this.IPAddress, this.port);
try {
this.serverSocket.send(sendPacket);
}
catch (IOException ex) {
ex.printStackTrace();
}
}
private void receivePackage() {
this.receiveData = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(this.receiveData, this.receiveData.length);
System.out.println("Waiting for packet...");
try {
this.serverSocket.receive(receivePacket);
this.sentence = new String(receivePacket.getData());
this.IPAddress = receivePacket.getAddress();
this.port = receivePacket.getPort();
}
catch (IOException ex) {
ex.printStackTrace();
}
}
private void splitPackage(String sentence) {
this.str = sentence.split("\\+");
for (String s: this.str) {
System.out.println(s);
}
}
Try making your Server class implementing Runnable, and put your loop in a run() method (overrided from Runnable).
Once done, you'll juste have to create your Server, and start it with : new Thread(yourServerName).start();
By doing so, your server will run "in the background" and listen to entering communications, allowing you to run other processes at the same time.
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.
At work we are developing an android app that communicates with set top boxes(STB).
It all works fine but I'm trying to create a "mock" STB that the app can connect to so I can control the responses for testing.
I have no access to the code in the STB to know how they set up the sockets but I do have a simplified version of the client code used by the app.
Here's the client code:
public class UDPClient {
public static void main(String[] args) throws SocketException, UnknownHostException {
DatagramSocket c = new DatagramSocket(12345);
c.setBroadcast(true);
c.setSoTimeout(20000);
String msearchData = "DATA";
byte[] sendData = mSearchData.getBytes();
try {
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName("239.255.255.250"), 1900);
c.send(sendPacket);
System.out.println("Request packet sent");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// wait for reply
byte[] recBuf = new byte[15000];
DatagramPacket receivePacket = new DatagramPacket(recBuf, recBuf.length);
try {
c.receive(receivePacket);
System.out.println("PACKET RECEIVED!");
System.out.println(new String(receivePacket.getData()));
} catch (IOException e) {
e.printStackTrace();
}
c.close();
}
}
When I run this code on my development laptop (and I'm on a wireless network with that STB) the STB responds.
However, I have another laptop setup to pretend to be another STB on the same network(mock STB).
The "mock" STB simply refuses to pick up the broadcasts requests and I'm stuck.
Here's some code I use to act as the mock STB. I've tried various combinations of ports but nothing works.
public class MockBox {
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket();
socket.setBroadcast(true);
while (true) {
System.out.println(">>>Ready to receive broadcast packets!");
byte[] recvBuf = new byte[15000];
DatagramPacket packet = new DatagramPacket(recvBuf, recvBuf.length);
socket.receive(packet); // blocks
// Packet received
System.out.println(">>>Packet received from " + packet.getAddress().getHostAddress());
System.out.println(">>>Packet data: " + new String(packet.getData()));
socket.close();
}
}
}
Any help appreciated!
Disable the software firewall.
Use MulticastSocket instead of DatagramSocket. (Note: The address you specified above is a multicast address.)
Use TTL of at least 1. If that doesn't work, use 2. Repeat, but don't go above say 4 or 5 on a LAN, because at that point, you're already past reasonable. (Zero won't leave the machine. Using a value too high may cause the packet to be discarded somewhere along the route.)
EDIT: The code below throws no exception but has no output and hangs. It should output "Test message". In main(), we start a thread that's given a server socket listening on a random port. The main thread the tries to connect and communicate with the ServerSocket on that same random port, but is apparently failing. Why?
public class IntraProcSockTest {
private static int port;
private class Listener extends Thread {
public Listener() {
}
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(0);
port = serverSocket.getLocalPort();
Socket socket = serverSocket.accept();
BufferedReader in;
String fromClient;
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
while ((fromClient = in.readLine()) != null) {
System.out.println("From client: " + fromClient);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public IntraProcSockTest() {
new Listener().start();
}
public static void main(String[] args) {
new IntraProcSockTest();
try {
Thread.sleep(5000);
Socket socket = new Socket("localhost", port);
PrintWriter socketOut = new PrintWriter(socket.getOutputStream());
socketOut.println("Test message");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
A process can connect to a socket created by itself, there is no problem. Show us the code that throws an exception and/or more details about the exception.
First of all, be careful not to specify a local port for the client socket (the one connecting to the other which is listening). Let the OS choose a random port. Remember that any socket is identified by four elements (remote host, local host, remote port, local port), if you bind both the server socket and the client socket on the same local port, let it be 4498, both sockets are defined as follows: (localhost, localhost, 4498, 4498) and this doesn't work. I suspect this might be your problem.
To avoid such problems, client sockets are often bound to a random port, chosen by the OS. Show us your code, expecially the part in which the client sockets gets created and connects to the server socket.
And about IPC, it is not always bad to use sockets as an inter-process or even intra-process communication technique. The performance is worse, obviously, and you might loose some code readability, but your software will be easily portable to a network (distributed) application. It's up to your plans, it's not like IPC sockets == bad.
To create a Socket connection in one thread you can.
ServerSocket ss = new ServerSocket(0); // open a random free port.
Socket c = new Socket(ss.getInetAddress(), ss.getLocalPort());
Socket s = ss.accept();
ss.close();
final byte[] bytes = "Hello World!".getBytes();
final OutputStream out = c.getOutputStream();
out.write(bytes.length);
out.write(bytes);
final DataInputStream in = new DataInputStream(s.getInputStream());
int len = in.read();
final byte[] b = new byte[len];
in.readFully(b);
System.out.println(new String(b));
c.close();
s.close();
If all you want is IPC within a Process, a socket is not the fastest or simplest way to go. Try using a Pipe (NIO) or PipeInput/OutputStream (IO). Its faster and simpler.
Pipe pipe = Pipe.open();
SinkChannel sink = pipe.sink();
SourceChannel source = pipe.source();
or
PipedOutputStream output = new PipedOutputStream();
PipedInputStream input = new PipedOutputStream(output);
BTW: You can connect a client and server Socket in the same thread, however
Using an Exchanger is 10x faster, and using a ring buffer is faster again.
If you want convenience, using an ExecutorService is the best way to deleagte work to a background pool of threads. This can still perform millions of tasks per second.