Java IP Multicast issue when sender and receiver on different node - java

Hi I am trying out java multicast.
I have a WIFI router at - 10.0.0.1 (gateway)
and two nodes:
Node_1 - 10.0.0.4
Node_2 - 10.0.0.3
My IP Multicast sender looks like:
private static class Sender extends Thread
{
// Create the socket but we don't bind it as we are only going to send data
private MulticastSocket s;
private static int senderPort = 15000;
private static String group = "225.4.5.6";
public Sender() throws IOException
{
s = new MulticastSocket(senderPort);
s.setInterface(InetAddress.getLocalHost());
s.joinGroup(InetAddress.getByName(group));
}
#Override
public void run() {
Integer data = 1;
while(true)
{
try {
s.send(new DatagramPacket(data.toString().getBytes(), data.toString().getBytes().length, InetAddress.getByName(group), senderPort));
Thread.sleep(3000);
data++;
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
System.out.println("Sender - UnknownHostException");
}catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("Sender - IOException");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
And my IP Multicast receiver looks like:
private static class Receiver extends Thread
{
private MulticastSocket s;
private static int receiverPort = 15000;
private static String group = "225.4.5.6";
public Receiver() throws IOException
{
s = new MulticastSocket(receiverPort);
s.setInterface(InetAddress.getLocalHost());
s.joinGroup(InetAddress.getByName(group));
}
#Override
public void run() {
while (true)
{
byte buf[] = new byte[1024];
DatagramPacket pack = new DatagramPacket(buf, buf.length);
try {
System.out.println("Receiver waiting for data");
s.receive(pack);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.write(pack.getData(),0,pack.getLength());
System.out.println();
}
}
}
When I have both the Sender and Receiver in the same Node it WORKS but when I have them in different Nodes it does NOT WORK.
What is it that I am missing here??

By calling setInterface() to the local host you are preventing the joinGroup() message from leaving the current host. That doesn't matter in the sender, because a sender doesn't have to join the group anyway, but in the receiver it will prevent other hosts, routers, etc. from knowing that the receiving host is in the group.
Just remove it.

Related

Multithreaded UDP Server Java

I have two threads, one is listening on a socket and adding to the queue, the other subtracting from the queue and submitting for processing. The second thread has a sleep when the queue is empty. This sleep somehow affects the first thread, that is, if you remove sleep or make it larger, then the delay in socket.receive of the first thread increases. If I keep the sleep as low as possible, it gets better, but not perfect. What am I doing wrong?
private DatagramSocket socket;
private boolean running, listenthreadwork;
private byte[] buf = new byte[256];
private List<IUDPListener> listeners = new ArrayList<IUDPListener>();
private Thread runnerThread, listenerThread;
private ConcurrentLinkedQueue<MyObject> list = new ConcurrentLinkedQueue<MyObject>();
public void init(int port) throws SocketException
{
socket = new DatagramSocket(port);
runnerThread = new Thread(this::listenLoopUDP);
runnerThread.setName("listenLoopUDP");
listenerThread = new Thread(this::listenerThreadUDP);
listenerThread.setName("listenerThreadUDP");
running = true;
listenthreadwork = true;
runnerThread.start();
listenerThread.start();
}
private void listenerThreadUDP() {
while (listenthreadwork == true) {
MyObjectinfo = null;
synchronized (list) {
if (!list.isEmpty()) {
info = list.poll();
}
}
if (info != null) {
for (IUDPListener listener : listeners) {
listener.msgReceived(info);
}
} else {
try {
Thread.sleep(10);//Somehow affects listenLoopUDP
} catch (InterruptedException e) {
Log.write(e);
}
}
}
}
public void listenLoopUDP() {
while (running) {
DatagramPacket packet = new DatagramPacket(buf, buf.length);
try {
socket.receive(packet);
} catch (IOException e) {
if (socket.isClosed()) {
running = false;
continue;
} else {
Log.write(e);
socket.close();
}
}
String received = new String(packet.getData());
MyObject info = new MyObject(received);
synchronized (list) {
list.offer(info);
}
}
listenthreadwork = false;
try {
listenerThread.join();
} catch (InterruptedException e) {
Log.write(e);
}
}
I have a simple client with timer
public class TestClient {
private DatagramSocket socket;
private InetAddress address;
private int count = 0;
public TestClient() {
try {
socket = new DatagramSocket();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
address = InetAddress.getByName("localhost");
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void sendEcho(String msg) {
msg = msg + count++;
ByteBuffer bb = ByteBuffer.allocate(256);
bb.order(ByteOrder.LITTLE_ENDIAN);
bb.put(msg.getBytes());
DatagramPacket packet = new DatagramPacket(bb.array(), bb.capacity(), address, 15000);
try {
socket.send(packet);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void close() {
socket.close();
}
}
TestClient client = new TestClient();
Timer timer = new Timer(false);
timer.schedule(new TimerTask() {
#Override
public void run() {
client.send("hello");
}
}, 1, 1);
But in server I get message something like this
2021-05-17 20:04:48.320
2021-05-17 20:04:48.335
2021-05-17 20:04:48.351
2021-05-17 20:04:48.367
2021-05-17 20:04:48.382
It doesn't even help to remove it or not run listenerThread
synchronized (list) {
list.offer(info);
}
Actually you don't need to sleep, use proper queue classes instead, like LinkedBlockingQueue, I also remove the flags since you don't need them also, use interrupt() to stop a thread blocked waiting for a queue element:
private DatagramSocket socket;
private byte[] buf = new byte[256];
private List<IUDPListener> listeners = new ArrayList<IUDPListener>();
private Thread runnerThread, listenerThread;
private LinkedBlockingQueue<MyObject> list = new LinkedBlockingQueue<MyObject>();
public void init(int port) throws SocketException
{
socket = new DatagramSocket(port);
runnerThread = new Thread(this::listenLoopUDP);
runnerThread.setName("listenLoopUDP");
listenerThread = new Thread(this::listenerThreadUDP);
listenerThread.setName("listenerThreadUDP");
runnerThread.start();
listenerThread.start();
}
private void listenerThreadUDP() {
try {
while (true) {
MyObject info=list.take();
for (IUDPListener listener : listeners) {
listener.msgReceived(info);
}
}
} catch (InterruptedException ex) {
//Just quit
}
}
public void listenLoopUDP() {
try {
while (true) {
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
String received = new String(packet.getData());
MyObject info = new MyObject(received);
list.put(info);
}
} catch (IOException e) {
Log.write(e);
} catch (InterruptedException e) {
Log.write(e);
} finally {
//Any exception above (or a runtime one) will activate this block where we do the cleanup and interrupt the other running thread
listenerThread.interrupt();
socket.close();
}
}
I did a test with your 1ms client, printing both sent and received message and I have a perfect interleaving between the message, so the bottleneck is not in the receiving thread; with perfect interleaving I mean that in the console I get, as expected, the sent message from the client immediately followed from the received message.

Simple UDP link

Hallo I need to write a very simple app that sends and retrieve data trough an UDP link (on Android OS, API level > 18):
This's a piece of code I used in an application I wrote sometime ago to connect trough TCP/IP (and doing the same thing):
class LinkReader implements Runnable
{
private final int mPort;
private final String mAddress;
private final Socket mLinkSocket;
public LinkReader(String address, int port, Socket link_socket)
{
mLinkSocket = link_socket;
mPort = port;
mAddress = address;
}
#Override
public void run()
{
try {
BufferedReader input = new BufferedReader(
new InputStreamReader(
mLinkSocket.getInputStream()
)
);
while (true)
{
Thread.sleep(100);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
class LinkThread implements Runnable {
private final int mPort;
private final String mAddress;
private Socket mLinkSocket;
public LinkThread(String address, int port, Socket socket)
{
mLinkSocket = socket;
mPort = port;
mAddress = address;
}
#Override
public void run()
{
try
{
mLinkSocket = new java.net.Socket(
InetAddress.getByName(mAddress),
mPort
);
new Thread(new LinkReader(mAddress,mPort,mLinkSocket)).start();
}
catch (UnknownHostException e) {
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
private void sendCommand(String cmd, Socket socket)
{
try
{
PrintWriter _out = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream()
)
),
false
);
_out.print(cmd);
_out.flush();
}
catch (UnknownHostException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (Exception e)
{
e.printStackTrace();
}
}
I've not been able to find an example about UDP connection on Android OS and I tought to reuse this code mainly because it was working pretty good (but I have to admint that I had not a very deep knowlede of Android neither I had very hight performances expectations from this piece of code).
Besides it was working in my past application my question is it correct now, in terms of code structure and aging?
How can I modify this to establish an UDP connection?
BTW Up to now I don't need really a R/W connection (I just need to send commands over there).

Cannot able to establish an UDP connection between a client and server [duplicate]

This question already has an answer here:
(How) can I use ServerSocket to listen for UDP instead of TCP traffic?
(1 answer)
Closed 5 years ago.
Basically, I am writing a simple TCP-UDP multiclient GUI program. I can establish a TCP connection to the server but not an UDP connection. The server is listening in on port 4000. I have a comboBox on the GUI client which has elements TCP and UDP. If the user selects UDP and clicks Connect. Then it will attempt to establish a UDP connection by calling the UDPconnection method.
Here is my code for the client GUI:
public void UDPconnection()
{
try
{
done = false;
datagramSocket = new DatagramSocket(serverPort);
}
catch (SocketException e)
{
done = true;
System.out.println("Host not available");
}
}
Here is my code for the chat server:
public class chatServer2 implements Runnable {
private int clientCount = 0;
private ChatServerThread clients[] = new ChatServerThread[50];
private ServerSocket server = null;
Thread thread = null;
//same as version3
public chatServer2(int port){
try{
server = new ServerSocket(port);//step1
System.out.println("Started the server...waiting for a client");
start(); //the chatserver's start method that goes ahead and creates a new thread
}
catch(IOException e){
System.err.println("ERROR "+e.getMessage());
}
}
public void start(){
if(thread == null){
thread = new Thread(this);
thread.start();
}
}
#Override
public void run() {//same as version 3
while(thread !=null){
try{
System.out.println("Waiting for a client...");
//now we add a new Thread and accept a client
addThread(server.accept());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void addThread(Socket socket){
if(clientCount < clients.length){
clients[clientCount] = new ChatServerThread(this, socket);
try {
clients[clientCount].open();//open the stream for the ChatServerThread client
clients[clientCount].start();//start to run the ChatServerThread client
clientCount++;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public synchronized void handle(int ID, String input)
{
System.out.println(input);
if(input.equalsIgnoreCase("bye"))
{
remove(ID);//person said bye so remove them
}
else
{
System.out.println(input);
for (int i = 0; i < clientCount; i++)
{
clients[i].send("User: " + ID + ": " + input);
}
}
}
public synchronized void remove(int ID){
int position = findClient(ID);
if(position >=0){
ChatServerThread toRemove = clients[position];
if(position <clientCount-1){
for(int i= position+1; i <clientCount; i++){
clients[i-1] = clients[i];
}
clientCount--;
}
try {
toRemove.close();//close the person's that said bye connection
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private int findClient(int ID){
for(int i=0; i<clientCount; i++){
if(clients[i].getID() == ID){
return i;
}
}
return -1;//not in the array
}
public static void main(String [] args){
chatServer2 l = new chatServer2(4000);
}
}
There is no such thing as a 'UDP connection', for a start.
Failure to create a DatagramSocket on a specified port does not mean 'host not available'. Have a look at the exception message to see what it does mean.
UDP does not interoperate with TCP, and specifically not with Java ServerSockets. You need a DatagramSocket or DatagramChannel at both ends, and there is no connect phase: you just send datagrams back and forth.

Always get Broken pipe use sendUrgentData in my Socket Client

I wrote a SocketClient for connect to the socket, and add some callback in it.
public class SocketClientV2 {
public static void main(String[] args) {
SocketClientV2.Listener listener = new SocketClientV2.Listener() {
#Override
public void recv(byte[] result) {
// TODO Auto-generated method stub
System.out.println("====recv something");
}
#Override
public void connected() {
// TODO Auto-generated method stub
System.out.println("=====connected!");
}
#Override
public void disconnect() {
// TODO Auto-generated method stub
System.out.println("=====disconnect!");
}
};
SocketClientV2 client = new SocketClientV2("172.16.16.102", 4444,
10000, listener);
byte[] test = new byte[10];
test[0] = (byte) 0x1c;
test[1] = (byte) 0xff;
test[2] = (byte) 0x08;
client.send(test);
}
public interface Listener {
public void recv(byte[] result);
public void connected();
public void disconnect();
}
Socket client = null;
boolean isConnect = false;
OutputStream outputStream = null;
InputStream inputStream = null;
public SocketClientV2() {
}
Listener cb = null;
public SocketClientV2(String site, int port, int timeout, Listener cb) {
this.cb = cb;
try {
client = new Socket(site, port);
client.setSoTimeout(timeout);
System.out.println("Client is created! site:" + site + " port:"
+ port);
if (isConnected()) {
isConnect = true;
if (cb != null) {
cb.connected();
}
checkConnect();
listenRecv();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public Socket getClient() {
return this.client;
}
public void closeSocket() {
try {
isConnect = false;
inputStream.close();
outputStream.close();
client.close();
client = null;
} catch (IOException e) {
e.printStackTrace();
}
}
private boolean isConnected() {
try {
client.sendUrgentData(0xff);
isConnect = true;
} catch (Exception e) {
System.out.println("return false....2");
isConnect = false;
e.printStackTrace();
return false;
}
return true;
}
private void checkConnect() {
new Thread() {
#Override
public void run() {
// TODO Auto-generated method stub
System.out.println("check connect....1");
try {
while (isConnected()) {
Thread.sleep(500);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
System.out.println("finally....3");
if (cb != null) {
cb.disconnect();
}
closeSocket();
}
}
}.start();
}
private void listenRecv() {
new Thread() {
#Override
public void run() {
// TODO Auto-generated method stub
System.out.println("listening Recv....");
try {
inputStream = client.getInputStream();
while (isConnect) {
byte[] result = readStream(inputStream);
if (cb != null) {
cb.recv(result);
}
Thread.sleep(500);
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
}
public void send(final byte[] byteSend) {
new Thread() {
#Override
public void run() {
// TODO Auto-generated method stub
// System.out.println("sendMsg coming....");
if (isConnect) {
try {
outputStream = client.getOutputStream();
outputStream.write(byteSend);
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
}
public byte[] readStream(InputStream inStream) throws Exception {
int count = 0;
while (count == 0) {
// System.out.println(0);
count = inStream.available();
// if(count!=0)
// System.out.println(count);
}
byte[] b = new byte[count];
inStream.read(b);
return b;
}
}
there is one thread checkConnect to check the connect status for the socket..
but it will disconnect after running few mins,
Client is created! site:172.16.16.102 port:4444
=====connected!
check connect....1
listening Recv....
====recv something
====recv something
====recv something
====recv something
====recv something
====recv something
====recv something
return false....2
java.io.IOException: Broken pipe
at java.net.PlainSocketImpl.socketSendUrgentData(Native Method)
at java.net.PlainSocketImpl.sendUrgentData(PlainSocketImpl.java:622)
at java.net.Socket.sendUrgentData(Socket.java:954)
at com.udpdemo.multicast.SocketClientV2.isConnected(SocketClientV2.java:100)
at com.udpdemo.multicast.SocketClientV2.access$0(SocketClientV2.java:98)
finally....3
=====disconnect!
at com.udpdemo.multicast.SocketClientV2$2.run(SocketClientV2.java:121)
java.io.IOException: Stream closed.
at java.net.PlainSocketImpl.available(PlainSocketImpl.java:483)
at java.net.SocketInputStream.available(SocketInputStream.java:217)
at com.udpdemo.multicast.SocketClientV2.readStream(SocketClientV2.java:205)
at com.udpdemo.multicast.SocketClientV2$3.run(SocketClientV2.java:154)
so what's problem with my sendUrgentData???
'Broken pipe' always means that you wrote to a connection which had already been closed by the peer. It's an application protocol error.
But unless the peer of this client isn't written in Java there is no point in using urgent data in the first place. Java can only receive urgent data 'in-line', i.e. after all the other pending data that had already been sent. And that only happens if the peer calls setOOBLine(true), otherwise
by default, this option is disabled and TCP urgent data received on a socket is silently discarded.
It's possible you're doing this to detect a broken connection. In this case, your dream came true, it worked, and all you have to do is adjust your catch and your code accordingly. But this is not in general a reliable technique.
Other notes:
isConnected() can never be false at the point you test it after creating the Socket, and it never magically becomes false afterwards. You need to revisit all the code that calls this method. Most of it doesn't make sense, or relies on false assumptions.
Your readStream() method spin-loops while available() returns zero. There is absolutely no point in this. You're just smoking the CPU. It's also completely at odds with your attempted use of a read timeout, which simply cannot possibly work while this loop is there. The following read() call will block until at least one byte of data arrives, or end of stream or an exception occurs. Your present code will never detect end of stream. You need to completely redesign this part of the code as well. It's poor practice to return a byte array for example.
That same piece of code completely ignores the count returned by read(). Never do that.

Variable not change the valor in the thread

I'm doing a routing protocol packets between nodes and I have the following issue that I think is related threads, which are overwriting the variables, but do not know how to fix it. I have the code where the error is as follows:
pclass nodosVecinos extends Thread {
public static int port = 0;
String num_Nodo = "";
byte[] buf = new byte[10000];
public synchronized void run() {
DatagramPacket dP = new DatagramPacket(buf, buf.length);
DatagramSocket sK = null;
try {
System.out.println(port);
sK = new DatagramSocket(this.port);//<-- Problem
} catch (SocketException e) {
System.out.println("problem node "+num_Nodo);
e.printStackTrace();
}
System.out.println("Node "+ num_Nodo +" up!"); // Nodo 1 encendido!
while(true){
try {
sK.receive(dP);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("Problem node , While");
}
System.out.println(buf.toString());
}
}
public nodosVecinos (int puerto){
port = puerto;
num_Nodo = Integer.toString(port);
num_Nodo = num_Nodo.substring(num_Nodo.length()-1,num_Nodo.length()); // 8001 => 1
}
public static void main(String args[]) {
}
}
i get out whit breackpoint :
8001 // <--- out in terminal
-1 // <--- Whit breackpoint and error.
I try write static the variable port but no go .
Thx for your help.
Edit:
The port is extern of synchronized , is class variable.
How do you start the threads?
Maybe "synchronized" is the problem. It causes that the whole method is executed before a new thread can start, but this method is infinite.

Categories