I started to using mina to do async writes to the socket, but now I can't seem to close the sessions. Is there a way to force mina to close all the managed sessions or clean up? There what i have for the clean right now:
if(this.acceptor.isActive()) {
for(IoSession session : this.acceptor.getManagedSessions().values()) {
session.close(true);
}
this.acceptor.unbind();
this.acceptor.dispose();
}
Thanks
Where did you put that code?
I just used for loop like below and all sessions were closed. First, run the server and start 3 clients in 10 seconds. You will see all clients' sessions will be closed when 10 secs is up.
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
public class MinaServer {
public static void main(String[] args) throws Exception {
IoAcceptor acceptor = new NioSocketAcceptor();
acceptor.getFilterChain().addLast("logger", new LoggingFilter());
acceptor.getFilterChain().addLast(
"codec",
new ProtocolCodecFilter(new TextLineCodecFactory(Charset
.forName("UTF-8"))));
acceptor.setHandler(new ServerHandler());
acceptor.bind(new InetSocketAddress(1071));
Thread.sleep(10000);
if (acceptor.isActive()) {
for (IoSession ss : acceptor.getManagedSessions().values()) {
ss.close(true);
}
}
}
}
Related
This question already has an answer here:
Address reuse not working on new Java Runtime Environment
(1 answer)
Closed 5 years ago.
Maybe I misunderstand the use of this code, but from what I understand, calling setReuseAddress(true) will allow the port to be used even if the computer still thinks it is in use.
Scenario: I have the below code. When it crashes it does not close the port, so it throws a bind error on next launch. I have used setReuseAddress(true) to try to force it to open the port, but it throws the same error. If this is the right code, how do I use it? If it's the wrong code, what will allow this behavior?
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
public class ServerPsswd {
public static void main(String[] args) throws IOException {
ServerSocket listener = new ServerSocket();
listener.setReuseAddress(true);
listener.bind(new InetSocketAddress(9090));
try {
while (true) {
Socket socket = listener.accept();
try {
PrintWriter out =
new PrintWriter(socket.getOutputStream(), true);
out.println("tada!");
out.println("yays");
} finally {
socket.close();
}
}
}
finally {
listener.close();
}
}
}
https://docs.oracle.com/javase/7/docs/api/java/net/Socket.html#setReuseAddress(boolean)
It is to allow connections during the timeout period AFTER the current connection has been closed
This is my server side code in java listening on port 1880 and making http client request from browser/client.java code in localhost which gives connection refused error.I copied that server code from a webpage.I am not sure what exactly this code is doing.
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerHandlingHttpRequest {
public void start() throws IOException
{
InetSocketAddress addr=new InetSocketAddress(1880);
System.out.println(addr.getPort());
System.out.println(addr.getAddress());
System.out.println(addr.getHostName());
System.out.println(addr.toString());
HttpServer server=HttpServer.create(addr,0);
server.createContext("/", new MyHandler());
server.setExecutor(null);
server.start();
System.out.println("Server Listening");
System.out.println(server.getAddress());
server.stop(60);
}
class MyHandler implements HttpHandler {
public void handle(HttpExchange t) throws IOException {
System.out.println("Request Arrived");
String response = "This is the response";
t.sendResponseHeaders(200, response.length());
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
public static void main(String[] args) throws IOException
{
ServerHandlingHttpRequest w=new ServerHandlingHttpRequest();
w.start();
}
}
That code simply starts listening to the port that you have specified, as an HTTP listener. Which means, any HTTP Request that might come into that port will be intercepted by your program. And when it intercepts, it looks for the context path that you have configured to handle the response to the request.
So, when you run this program, it starts listening at port 1880. When a URL http://localhost:1880/ is hit, it will be intercepted by the handler, MyHandler. The response will be written to the OutputStream which will send back the request back to the client.
One of the problems that I see is that you are stopping the server after printing some statements, while the example that you have refered is not doing so. May be, remove server.stop(60) statement and check whether the issue still persists.
I am using CuratorFramework (I'm still a newbie) in order to connect to a Zookeeper instance. I would like to import a configuration but before that I would like to test that my program is able to connect to Zookeeper. So far I have something like that:
public Boolean zookeeperRunning() {
CuratorFramework curatorFramework =
CuratorFrameworkFactory.newClient(zookeeperConn, new RetryOneTime(1));
curatorFramework.start();
CuratorZookeeperClient zkClient = curatorFramework.getZookeeperClient();
return zkClient.isConnected();
}
I've already started ZooKeeper on my local machine and I checked the connection with zkCli and the client is able to connect to it. The zookeeperCon variable is set to "127.0.0.1:2181" (I tried with localhost:2181 as well). The problem is that the above method always returns false despite the fact that zkServer is up n running. Most probably, the syntax is not correct but I could not find a solution online. Could you please help me with why the above code cannot find the zkServer which is up and running?
You can use a builder to create a configured client and setup a listener to monitor your zk instance's state:
// start client
client = CuratorFrameworkFactory.builder()
.connectString("localhost:2181")
.retryPolicy(new ExponentialBackoffRetry(1000, 3))
.namespace("heavenize")
.build();
client.getConnectionStateListenable().addListener(new ConnectionStateListener() {
#Override
public void stateChanged(CuratorFramework client, ConnectionState newState)
{
log.info("State changed to: "+newState);
}
});
}
You should first connect to zookeeper after you get the zkClient, if success, then check the isConnected status. Demo code below(Refer: here):
private static CuratorFramework buildConnection(String url) {
CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient(url, new ExponentialBackoffRetry(100, 6));
// start connection
curatorFramework.start();
// wait 3 second to establish connect
try {
curatorFramework.blockUntilConnected(3, TimeUnit.SECONDS);
if (curatorFramework.getZookeeperClient().isConnected()) {
return curatorFramework.usingNamespace("");
}
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
}
// fail situation
curatorFramework.close();
throw new RuntimeException("failed to connect to zookeeper service : " + url);
}
you should connect to zookeeper server then check it. for example:
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.test.TestingServer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertTrue;
public class ZkClientTest {
TestingServer zkServer;
#Before
public void startZookeeper() throws Exception {
zkServer = new TestingServer(2181);
zkServer.start();
}
#After
public void stopZookeeper() throws IOException {
zkServer.stop();
}
#Test
public void should_connect_to_zookeeper_server_when_config_use_default_localhost_2181()
throws InterruptedException {
CuratorFramework client = ZkClient.getInstance().getClient();
try {
client.blockUntilConnected(3, TimeUnit.SECONDS);
assertTrue(ZkClient.getInstance().getClient().getZookeeperClient().isConnected());
} finally {
ZkClient.getInstance().close();
}
}
}
I have the following clientendpoint class for a websocket in tomcat 7.0.53. It is based off of this example on a website https://blog.openshift.com/how-to-build-java-websocket-applications-using-the-jsr-356-api/
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import javax.websocket.ClientEndpoint;
import javax.websocket.CloseReason;
import javax.websocket.ContainerProvider;
import javax.websocket.DeploymentException;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
#ClientEndpoint
public class connect {
private static ArrayList<Session> sessionList = new ArrayList<Session>();
public connect(URI endpointURI) throws DeploymentException, IOException
{
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.connectToServer(this, endpointURI);
}
#OnOpen
public void onOpen(Session session) throws IOException
{
sessionList.add(session);
System.out.println(session.getId());
session.getBasicRemote().sendText("hello");
}
public void sendMessage(String message) throws IOException
{
for(Session session : sessionList){
//asynchronous communication
session.getBasicRemote().sendText(message);
}
}
#OnClose
public void onClose(Session session){
sessionList.remove(session);
System.out.println("here");
}
#OnError
public void onError(Throwable t, Session session){
System.out.println("tedt");
}
}
I then have the following code to start the client endpoint
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import javax.websocket.DeploymentException;
public class test {
public static void main(String[] args) throws DeploymentException, IOException, URISyntaxException {
// TODO Auto-generated method stub
connect connect = new connect(new URI("ws://localhost:8080/example/talk"));
connect.sendMessage("now");
}
}
The client does successfully connect to the websocket server, however then it gets disconnected right away when I try to send a message or do anything, I know this since the onError function is being called when I try to send a message from the onOpen function. Why is the websocket getting closed immediately after it is connected to the server?
You are being disconnected because your main thread in your client application is ending. After you send "now", your program simply exits. If you want to do anything else (like wait for a response from the server, for instance), then you'll have to prevent the main thread from exiting. Try something like this at the end of your main method:
System.in.read();
This will cause your process to sit and wait for input from standard input. Simply wait for your test to complete and then press ENTER on the command-line to terminate the client.
You will, of course, want to register a handler for receiving messages back from the server to the client. Right now, you can only send messages from the client to the server.
Using JBOSS Netty, I'm trying to send data continuously to the connected client. In the example below,
I try to send the time every 5 secs to the client, as soon as the client gets connected (channelConnected).
But this is not working. It works only if I comment the while loop.
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.string.StringEncoder;
public class SRNGServer {
public static void main(String[] args) throws Exception {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Configure the pipeline factory.
bootstrap.setPipelineFactory(new SRNGServerPipelineFactoryP());
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(8080));
}
private static class SRNGServerHandlerP extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(SRNGServerHandlerP.class.getName());
#Override
public void channelConnected(
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
// Send greeting for a new connection.
e.getChannel().write("Welcome to " + InetAddress.getLocalHost().getHostName() + "!\r\n");
while(true){
e.getChannel().write("It is " + new Date() + " now.\r\n");
Thread.sleep(1000*5);
}
}
#Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) {
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
e.getChannel().close();
}
}
private static class SRNGServerPipelineFactoryP implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
// Create a default pipeline implementation.
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("handler", new SRNGServerHandlerP());
return pipeline;
}
}
}
The Netty documentation actually states that you should never make a Handler wait because it might eventually deadlock. The reason is that handler methods are called directly by I/O threads. One I/O thread in Netty performs multiple I/O operations in a sequence, so it's not one thread per operation.
In the channelConnected method you should start a new thread with a reference to the channel and make that thread send the time every 5 seconds. This would spawn one thread per connection.
Alternatively, you can have one single thread looping over a list of clients every 5 seconds and sending the time to each of them in a sequence.
Anyway, it's important to use a different thread for sending than the one that calls the Handler.
For what its worth, I figured the solution and here's the working code. After the "write" of time, I register the future with my ChannelFuturelistener. And then from operationComplete I keep registering the new future for every write. This works for what I want to accomplish, without using any extra threads.
import java.net.InetSocketAddress;
import java.nio.channels.ClosedChannelException;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.string.StringEncoder;
public class SRNGServer {
public static void main(String[] args) throws Exception {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
//Executors.newCachedThreadPool()
Executors.newFixedThreadPool(2),2
));
// Configure the pipeline factory.
bootstrap.setPipelineFactory(new SRNGServerPipelineFactoryP());
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(8080));
}
private static class SRNGServerHandlerP extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(SRNGServerHandlerP.class.getName());
#Override
public void channelConnected(
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
// Send greeting for a new connection.
Channel ch=e.getChannel();
ChannelFuture writeFuture=e.getChannel().write("It is " + new Date() + " now.\r\n");
SRNGChannelFutureListener srngcfl=new SRNGChannelFutureListener();
writeFuture.addListener(srngcfl);
}
#Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) {
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
if(e.getCause() instanceof ClosedChannelException){
logger.log(Level.INFO, "****** Connection closed by client - Closing Channel");
}
e.getChannel().close();
}
}
private static class SRNGServerPipelineFactoryP implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
// Create a default pipeline implementation.
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("handler", new SRNGServerHandlerP());
return pipeline;
}
}
private static class SRNGChannelFutureListener implements ChannelFutureListener{
public void operationComplete(ChannelFuture future) throws InterruptedException{
Thread.sleep(1000*5);
Channel ch=future.getChannel();
if(ch!=null && ch.isConnected()){
ChannelFuture writeFuture=ch.write("It is " + new Date() + " now.\r\n");
//-- Add this instance as listener itself.
writeFuture.addListener(this);
}
}
}
}
Seems that the I/O thread is getting blocked as a result of sleep, so try using 2 worker threads instead:
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory( Executors.newCachedThreadPool(),
Executors.newCachedThreadPool(), 2 ) );