Querying the client periodically for update via sockets-Reusing ports - java

using the Controller.java, I' implementing the run() in NetworkDiscovery.java which queries all the machine in the subnet . The active machines reply with their status. This happens at regular intervals.
public class Controller {
NetworkDiscovery n;
public static int discoveryInterval=2000;
PM pmList;
List pmlist=(List) new PM();
public static void main(String[] args) throws UnknownHostException{
Timer t1=new Timer();
t1.scheduleAtFixedRate(new NetworkDiscovery(), 2000, discoveryInterval);
}
public class NetworkDiscovery extends TimerTask{
InetAddress controllerIP;
int controllerPort;
NetworkDiscovery() throws UnknownHostException {
controllerIP=InetAddress.getLocalHost();
controllerPort=4455;
}
#Override
public void run() {
try {
byte[] recvBuf = new byte[5000];
DatagramPacket packet = new DatagramPacket(recvBuf, recvBuf.length);
DatagramSocket dSock = new DatagramSocket(4445);
dSock.receive(packet);
//implementation related code follows
**dSock.close();**
}
}
On the client's side a similar Datagram socket is opened and objects are received/sent.
The problem is that on the COntroller's side, I'm executing NetworkDiscovery's run() after a specific time interval and during the second execution it says -
java.net.BindException: Address already in use
Since I'm closing the Controller's socket by close(), why does it still show that this address is already being in use? How can I make sure that during the next iteration, the controller starts over fresh call of networkDiscovery?

Perhaps the second task starts before the first was completly executed? Have you tried to insert debug messages and see if the first task was finished?

Related

Communication in Netty Nio java

I want to create a communication system with two clients and a server in Netty nio. More specifically, firstly, I want when two clients are connected with the server to send a message from the server and after that to be able to exchnage data between the two clients. I am using the code provided from this example. My modifications in the code can be found here: link
It seems that the channelRead in the serverHandler works when the first client is connceted so it always return 1 but when a second client is connected does not change to 2. How can I check properly from the server when both clients are connected to the server? How can I read this value dynamically from my main function of the Client? Then which is the best way to let both clients communicate?
EDIT1: Apparently it seems that the client service is running and close directly so every time that I am running a new NettyClient is connected but the connection is closed after that. So the counter is always chnages from zero to one. As I was advised in the below comments I tested it using telnet in the same port and the counter seems to increasing normally, however, with the NettyClient service no.
EDIT2: It seems that the issue I got was from future.addListener(ChannelFutureListener.CLOSE); which was in channelRead in the ProcessingHandler class. When I commented it that out it seems that the code works. However, am not sure what are the consequences of commented that out. Moreover, I want from my main function of the client to check when the return message is specific two. How, could I create a method that waits for a specific message from server and meanwhile it blocks the main functionality.
static EventLoopGroup workerGroup = new NioEventLoopGroup();
static Promise<Object> promise = workerGroup.next().newPromise();
public static void callClient() throws Exception {
String host = "localhost";
int port = 8080;
try {
Bootstrap b = new Bootstrap();
b.group(workerGroup);
b.channel(NioSocketChannel.class);
b.option(ChannelOption.SO_KEEPALIVE, true);
b.handler(new ChannelInitializer<SocketChannel>() {
#Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new RequestDataEncoder(), new ResponseDataDecoder(), new ClientHandler(promise));
}
});
ChannelFuture f = b.connect(host, port).sync();
} finally {
//workerGroup.shutdownGracefully();
}
}
I want inside the main function to call the method and return the result and when it is 2 to continue with the main functionality. However, I cannot call callClient inside the while since it will run multiple times the same client.
callBack();
while (true) {
Object msg = promise.get();
System.out.println("Case1: the connected clients is not two");
int ret = Integer.parseInt(msg.toString());
if (ret == 2){
break;
}
}
System.out.println("Case2: the connected clients is two");
// proceed with the main functionality
How can I update the promise variable for the first client. When I run two clients, for the first client I always received the message :
Case1: the connected clients is not two
seems that the promise is not updated normally, while for the second client I always received the:
Case2: the connected clients is two
If my memory is correct, ChannelHandlerContext is one per channel and it can have multiple ChannelHandlers in it's pipeline. Your channels variable is an instance variable of your handler class. And you create a new ProcessingHandler instance for each connection. Thus each will have one and only one connection in channels variable once initialized - the one it was created for.
See new ProcessingHandler() in initChannel function in the server code (NettyServer.java).
You can either make channels variable static so that it is shared between ProcessingHandler instances. Or you can create a single ProcessingHandler instance elsewhere (e.g. as a local variable in the run() function) and then pass that instance to addLast call instead of new ProcessingHandler().
Why the size of ChannelGroup channels is always one. Even if I connect
more clients?
Because child ChannelInitializer is called for every new Channel (client). There you are creating new instance of ProcessingHandler, so every channel see its own instance of ChannelGroup.
Solution 1 - Channel Attribute
Use Attribute and associate it with Channel.
Create attribute somewhere (let's say inside Constants class):
public static final AttributeKey<ChannelGroup> CH_GRP_ATTR =
AttributeKey.valueOf(SomeClass.class.getName());
Now, create ChannelGroup which will be used by all instances of ProcessingHandler:
final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
Update your child ChannelInitializer in NettyServer :
#Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(
new RequestDecoder(),
new ResponseDataEncoder(),
new ProcessingHandler());
ch.attr(Constants.CH_GRP_ATTR).set(channels);
}
Now you can access instance of ChannelGroup inside your handlers like this:
#Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
final ChannelGroup channels = ctx.channel().attr(Constants.CH_GRP_ATTR).get();
channels.add(ctx.channel());
This will work, because every time new client connects, ChannelInitializer will be called with same reference to ChannelGroup.
Solution 2 - static field
If you declare ChannelGroup as static, all class instances will see same ChannelGroup instance:
private static final ChannelGroup channels =
new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
Solution 3 - propagate shared instance
Introduce parameter into constructor of ProcessingHandler:
private final ChannelGroup channels;
public ProcessingHandler(ChannelGroup chg) {
this.channels = chg;
}
Now, inside your NettyServer class create instance of ChannelGroup and propagate it to ProcessingHandler constructor:
final ChannelGroup channels = new
DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
#Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(
new RequestDecoder(),
new ResponseDataEncoder(),
new ProcessingHandler(channels)); // <- here
}
Personally, I would choose first solution, because
It clearly associate ChannelGroup with Channel context
You can access same ChannelGroup in other handlers
You can have multiple instances of server (running on different port, within same JVM)

Jar with multiple main

In one package I have two different classes Client.java and Server.java
I want to make this package jar, i mean executable.
First I want the Server class to run and after 2-3 seconds I want Client method to run. Is it possible?
Thank you
You have to leave only one main method and run your server and client in separate threads from it.
To do it, take a look at Runnable interface. Your server class and client class should implement it. Then you have to move the logic, used to start server and client to it's run() method.
class Server implements Runnable {
#Override
public void run() {
//your server starting logic here
}
}
class Client implements Runnable {
#Override
public void run() {
//your client starting logic here
}
}
After that, you can modify your main method, to start server and client, like:
public static void main(String args[]) throws InterruptedException {
Server server = new Server();
Client client = new Client();
Thread tServer = new Thread(server);
tServer.start();
//here you can wait some time to Server started
Thread tClient = new Thread(client);
tClient.start();
}

Sending multiple files in java callback?

How can I add to the sending queue, for example I choose a file with JFileChooser and then send it in a new thread to the client, and I want to choose another and send it as well. What happens is that it sends the files simultaneously and the output on the client side is broken.
I'd like to be able to add to a "queue" of some sort, so that when the first file is sent, the server will start sending the next one.
A good aproach for socket communication between server->client, is to have 1 thread per client and have this thread reading from a java.util.concurrent.BlockingQueue. Such interface is ideal (just like all the java.util.concurrent objects) for managing multithreading concurrency.
The idea, is that the Server has a ClientThread like this:
class BroadCastThread extends Thread{
LinkedBlockingQueue<SendFileTask> bcQueue = new LinkedBlockingQueue<>();
#Override
public void run() {
while( true ){
try {
SendFileTask task = bcQueue.take();
task.sendFile();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
void addTask(SendFileTask rt) throws InterruptedException{
bcQueue.put(rt);
}
}
interface SendFileTask{
void sendFile() throws Exception;
}
And use this by adding tasks to you thread object:
BroadCastThread bct = new BroadCastThread();
bct.start();
//With lambda
bct.addTask(() -> {
//Send file code
});
//Without lambda
bct.addTask(new SendFileTask() {
#Override
void sendFile() throws Exception {
//Send file code
}
});
You can even store the Socket information with the thread, and pass it throw the task interface, if you want the sendFile method to receive it as parameter.

Aperiodically trigger a thread to run in Java

My server aperiodically receives join requests from new clients. Upon receiving a new join request, the server runs a service that can be finished real quick. I implement the service as a Java class (called JC) implementing the Runnable interface. I have parameters within the JC class.
At the caller side, I like to have only one instance (or static) of the JC. My question is how to trigger the run() method in the JC every time. Please show me some code. Thanks.
Hope following edits make sense, which is my current implementation.
In the Server that wants to trigger thread executing:
public class Server {
private static RealService mm = new RealService();
private static void update(){
new Thread(mm).start();
}
}
In the Service class:
public class RealService implements Runnable{
#Override
public void run() {
// TODO Auto-generated method stub
// Do something
}
}
You're question is not really clear here, but I would suggest reading about TimerTask in Java
You could use a socket to listen for incoming requests, the server can spawn a new thread each time there is a request. Once the thread completes, you should intimate the client.
You could read about how a concurrent server works.

Fire and foget methods in JAVA, methods then u don't need to wait

I have an custom thread that waits for UDP packages. After receiving i want this thread to continue running and just send the information to another method. I checked #Asynchronous notation, but that seems to work only in javaEE. Any suggestions?
"I have an custom thread that waits for UDP packages" - That's your answer, have another thread that can process them.
I'd recommend taking a look at Executors. This way you can have multiple threads processing the incoming packets without the need to manage it all yourself
You can do something like this:
private static final ExecutorService threadPool = Executors.newCachedThreadPool();
InetAddress address = InetAddress.getByName("hostname");
while(true){
DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 4445);
threadPool.execute(new Runnable(){
public void run(){
processPacket(clientConnection); // write a method to do the packet processing
}
);
}
Another approach is using Queues.
The thread that waits for UDP packets places the packet it finds onto a BlockingQueue. Another thread continually polls that queue and processes whatever it finds.
for example:
public class UdpReceivingThread extends Thread {
private final BlockingQueue<UdpPacket> queue;
public UdpReceivingThread(BlockingQueue<UdpPacket> queue) {
this.queue = queue;
}
#Override
public void run() {
while (true) {
UdpPacket packet = listenForPacket();
queue.put(packet);
}
}
}
and
public class ProcessingThread extends Thread {
private final BlockingQueue<UdpPacket> queue;
public ProcessingThread(BlockingQueue<UdpPacket> queue) {
this.queue = queue; // Same queue instance as in UdpReceivingThread instances!
}
#Override
public void run() {
while(true) {
UdpPacket packet = queue.take();
process(packet);
}
}
}
Note that this approach is certainly related to using an Executor - an Executor essentially uses a BlockingQueue to manage Runnables, which wrap the method calls to process the UDP packet. This is just another way of doing it.

Categories