How to pass data between Channels in netty? - java

I am writing a simple routing application. The idea is that I have servers or source nodes that receive transient clients connections that last for a period of x time. The messages received are decoded and then sent to a corresponding sink node or client that is/are already open depending on the details of the message. The Router class registers all channels and attemps to save them in maps so that it can filter and worj out the destination of the message. Once I get the destination, I should then be able to pick the actual sink node (could be of transient of persistent nature depending on the configurations) and send data to that channel wait for a response and then send it back to the originator. I'd like to know first if my implementation using netty is in the right direction ? and how can I pass a message received from any of the servers and send it to any of the clients and respond back to the originating source node ?
Below is my source code : It will / should give you an idea of what I am up to :Kindly use code examples in your explanation .
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelFactory;
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.ChildChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
/*
* #author Kimathi
*/
public class Service {
private Nodes nodes;
public void start(){
nodes = new Nodes();
nodes.addSourceNodes(new SourceNodes()).
addSinkNodes(new SinkNodes()).
addConfigurations(new Configurations()).
boot();
}
public void stop(){
nodes.stop();
}
public static void main(String [] args){
new Service().start();
}
}
class Nodes {
private SourceNodes sourcenodes;
private SinkNodes sinknodes ;
private Configurations configurations;
public Nodes addConfigurations(Configurations configurations){
this.configurations = configurations;
return this;
}
public Nodes addSourceNodes(SourceNodes sourcenodes){
this.sourcenodes = sourcenodes;
return this;
}
public Nodes addSinkNodes(SinkNodes sinknodes){
this.sinknodes = sinknodes;
return this;
}
public void boot(){
Router router = new Router(configurations);
sourcenodes.addPort(8000).
addPort(8001).
addPort(8002);
sourcenodes.addRouter(router);
sourcenodes.boot() ;
sinknodes.addRemoteAddress("127.0.0.1", 6000).
addRemoteAddress("127.0.0.1", 6001).
addRemoteAddress("127.0.0.1", 6002);
sinknodes.addRouter(router);
sinknodes.boot();
}
public void stop(){
sourcenodes.stop();
sinknodes.stop();
}
}
final class SourceNodes implements Bootable , Routable {
private List <Integer> ports = new ArrayList();
private ServerBootstrap serverbootstrap;
private Router router;
#Override
public void addRouter(final Router router){
this.router = router;
}
public SourceNodes addPort(int port){
this.ports.add(port);
return this;
}
#Override
public void boot(){
this.initBootStrap();
this.serverbootstrap.setOption("child.tcpNoDelay", true);
this.serverbootstrap.setOption("child.keepAlive", true);
this.serverbootstrap.setPipelineFactory(new ChannelPipelineFactory() {
#Override
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(new SourceHandler(router));
}
});
for(int port:this.ports){
this.serverbootstrap.bind(new InetSocketAddress(port));
}
}
#Override
public void stop(){
this.serverbootstrap.releaseExternalResources();
}
private void initBootStrap(){
ChannelFactory factory = new NioServerSocketChannelFactory( Executors.newCachedThreadPool(),Executors.newCachedThreadPool());
this.serverbootstrap = new ServerBootstrap(factory);
}
}
final class SinkNodes implements Bootable , Routable {
private List<SinkAddress> addresses= new ArrayList();
private ClientBootstrap clientbootstrap;
private Router router;
#Override
public void addRouter(final Router router){
this.router = router;
}
public SinkNodes addRemoteAddress(String hostAddress,int port){
this.addresses.add(new SinkAddress(hostAddress,port));
return this;
}
#Override
public void boot(){
this.initBootStrap();
this.clientbootstrap.setOption("tcpNoDelay", true);
this.clientbootstrap.setOption("keepAlive", true);
this.clientbootstrap.setPipelineFactory(new ChannelPipelineFactory() {
#Override
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(new SinkHandler(router));
}
});
for(SinkAddress address:this.addresses){
this.clientbootstrap.connect(new InetSocketAddress(address.hostAddress(),address.port()));
}
}
#Override
public void stop(){
this.clientbootstrap.releaseExternalResources();
}
private void initBootStrap(){
ChannelFactory factory = new NioClientSocketChannelFactory( Executors.newCachedThreadPool(),Executors.newCachedThreadPool());
this.clientbootstrap = new ClientBootstrap(factory);
}
private class SinkAddress {
private final String hostAddress;
private final int port;
public SinkAddress(String hostAddress, int port) {
this.hostAddress = hostAddress;
this.port = port;
}
public String hostAddress() { return this.hostAddress; }
public int port() { return this.port; }
}
}
class SourceHandler extends SimpleChannelHandler {
private Router router;
public SourceHandler(Router router){
this.router = router;
}
#Override
public void childChannelOpen(ChannelHandlerContext ctx, ChildChannelStateEvent e) throws Exception {
System.out.println("child is opened");
}
#Override
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("child is closed");
}
#Override
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("Server is opened");
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
System.out.println(e.getCause());
}
#Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
System.out.println("channel received message");
}
}
class SinkHandler extends SimpleChannelHandler {
private Router router;
public SinkHandler(Router router){
this.router = router;
}
#Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("Channel is connected");
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
System.out.println(e.getCause());
}
#Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
System.out.println("channel received message");
}
}
final class Router {
private Configurations configurations;
private Map sourcenodes = new HashMap();
private Map Sinknodes = new HashMap();
public Router(){}
public Router(Configurations configurations){
this.configurations = configurations;
}
public synchronized boolean submitSource(ChannelHandlerContext ctx , MessageEvent e){
boolean responded = false;
return responded;
}
public synchronized boolean submitSink(ChannelHandlerContext ctx , MessageEvent e){
boolean responded = false;
return responded;
}
}
final class Configurations {
public Configurations(){}
}
interface Bootable {
public abstract void boot();
public abstract void stop();
}
interface Routable {
public abstract void addRouter(Router router);
}

The idea seems reasonable.
The source channel handler can just write to the corresponding sink channel, using Channel#write(...), and vice versa on the reply.
Of course, you also need a way to correlate the source channel with the reply, and how that is best done depends an the nature of the protocol. The best alternative, if possible, is to somehow encode the source channel id in the message to the sink channel (and also in the reply, of course).
If that is not possible, you will somehow have to maintain the correlation. A FIFO queue per sink channel may be appropriate if the replies are guaranteed to pair up with the sent requests.

Related

kryonet server crashing when receiving an object

I have a problem with Kryonet server crashing after receiving an object from client.
Server code:
package com.qookie.miner_server;
import java.io.IOException;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryonet.Server;
import com.esotericsoftware.minlog.Log;
import com.qookie.miner_server.Packet.*;
public class MinerServer_Main {
private Server server;
public MinerServer_Main() throws IOException {
this.server = new Server();
RegisterPackets();
server.addListener(new NetworkListener());
server.bind(8888,8888);
server.start();
}
private void RegisterPackets() {
Kryo kryo = server.getKryo();
kryo.register(Packet0LoginRequest.class);
kryo.register(Packet1LoginAnswer.class);
kryo.register(Packet2Message.class);
}
public static void main(String[] args) {
try {
new MinerServer_Main();
} catch (IOException e) {
e.printStackTrace();
}
}
}
And here is a server listener:
package com.qookie.miner_server;
import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.Listener;
import com.qookie.miner_server.Packet.*;
public class NetworkListener extends Listener {
public void connected(Connection arg0) {
System.out.println("[SERVER] Someone has connected");
}
public void disconnected(Connection arg0) {
System.out.println("[SERVER] Someone has disconnected");
}
public void received(Connection c, Object o) {
if (o instanceof Packet0LoginRequest) {
Packet1LoginAnswer p = new Packet().new Packet1LoginAnswer();
p.accepted = true;
c.sendTCP(p);
}
if (o instanceof Packet2Message) {
String message = ((Packet2Message) o).msg;
System.out.println("[CLIENT] " + message);
}
}
}
And here is Packet.java file:
package com.qookie.miner_server;
public class Packet {
public class Packet0LoginRequest {
public Packet0LoginRequest() {}
public void init() {
}
};
public class Packet1LoginAnswer {
public boolean accepted;
public Packet1LoginAnswer() {}
public void init() {
}
};
public class Packet2Message {
public Packet2Message() {}
public String msg;
public void init() {
}
};
public Packet() {
}
}
When user connects client sends a Packet0LoginRequest and server sends back Packet1LoginAnswer.
When boolean variable in Packet1LoginAnswer is true, client starts reading from scanner and sending new Packet2Message.
But the server crashes when receiving Packet0LoginRequest.
Here is the crash log:
Server crash log
It think kryonet fails to load your constructor.
Following approach worked from me:
public class Network {
static public final int tcpPort = 54555;
static public final int udpPort = 54777;
// This registers objects that are going to be sent over the network.
static public void register (EndPoint endPoint) {
Kryo kryo = endPoint.getKryo();
kryo.register(ServerResponse.class);
kryo.register(ClientRequest.class);
}
static public class ServerResponse {
...
public ServerResponse(){
super();
}
...
}
static public class ClientRequest {
...
public ClientRequest(){
super();
}
...
}
...
}

javax.net.ssl.SSLHandshakeException: Handshake failed on Android 5.0.0 when SSLv2 and SSlv3 are disabled (TLS only) (and greater)

This is my first post and I'm going to try to do my best to be as clear as possible (sorry for my english).
Here is my trouble, I'm using retrofit:1.9.0 and okhttp:2.7.5 to perform API call. Everything was fine until my server provider disable SLLv2 and SSLv3 cause of sercurity trouble (Drown fail found on first March).
Now I check the information about my provider and he allows only TLSv1 with cypher (TLS 1.0 TLS_RSA_WITH_3DES_EDE_CBC_SHA No FS) from https://www.ssllabs.com/.
Ok so this is all the tests I've done and results:
[UPDATE PROBLEM SOLVED]
Find a way to solve this problem in my second answer.
UPDATE
It seems that the problems comes from the google API version. When I test on API 18 everything is working fine. When it's on Android greather or equal to 5.0.0 it fails.
First test
Conf. recap:
compileSdkVersion 23
buildToolsVersion '23.0.2'
minSdkVersion 18
targetSdkVersion 21
retrofit:1.9.0
okhttp:2.7.5
Android version > 5.0.0 (but it's the same on every device...)
Rest Client (LoginRestClient):
public class LoginRestClient
{
private static final String BASE_URL = "";
private LoginApiService apiService;
public LoginRestClient()
{
Gson gson = new GsonBuilder()
.setDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'")
.create();
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint(ApiIntentService.getHostAddress())
.setConverter(new GsonConverter(gson))
.setClient(new OkClient(ApiIntentService.getConnectionHttpClient()))
.build();
apiService = restAdapter.create(LoginApiService.class);
}
public LoginApiService getApiService() {
return apiService;
}
}
Function to create client OkHttpClient getConnectionHttpClient()
public static OkHttpClient getConnectionHttpClient()
{
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setReadTimeout(60, TimeUnit.SECONDS);
okHttpClient.setConnectTimeout(60, TimeUnit.SECONDS);
ConnectionSpec specs = new ConnectionSpec.Builder(ConnectionSpec.COMPATIBLE_TLS)
.tlsVersions(TlsVersion.TLS_1_0)
.cipherSuites(CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA)
.build();
okHttpClient.setConnectionSpecs(Collections.singletonList(specs));
return okHttpClient;
}
Result in public void failure(RetrofitError error) from custom CallBack
java.net.UnknownServiceException: Unable to find acceptable protocols. isFallback=false, modes=[ConnectionSpec(cipherSuites=[TLS_RSA_WITH_3DES_EDE_CBC_SHA], tlsVersions=[TLS_1_0], supportsTlsExtensions=true)], supported protocols=[SSLv3, TLSv1, TLSv1.1, TLSv1.2]
Second test
I've made a custom SSLSocketFactory to disable SSLv3 and force TLS:
/**
* #author fkrauthan
*/
public class TLSSocketFactory extends SSLSocketFactory {
private SSLSocketFactory internalSSLSocketFactory;
public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, null, null);
internalSSLSocketFactory = context.getSocketFactory();
}
#Override
public String[] getDefaultCipherSuites() {
return internalSSLSocketFactory.getDefaultCipherSuites();
}
#Override
public String[] getSupportedCipherSuites() {
return internalSSLSocketFactory.getSupportedCipherSuites();
}
#Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose));
}
#Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}
#Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort));
}
#Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}
#Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort));
}
private Socket enableTLSOnSocket(Socket socket) {
if(socket != null && (socket instanceof SSLSocket)) {
((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1"});
}
return socket;
}
}
I use it like this:
public static OkHttpClient getConnectionHttpClient()
{
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setReadTimeout(60, TimeUnit.SECONDS);
okHttpClient.setConnectTimeout(60, TimeUnit.SECONDS);
try {
TLSSocketFactory tlsSocketFactory = new TLSSocketFactory();
HttpsURLConnection.setDefaultSSLSocketFactory(tlsSocketFactory);
okHttpClient.setSslSocketFactory(tlsSocketFactory);
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return okHttpClient;
}
Result in public void failure(RetrofitError error) from custom CallBack
javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x7f87885280: Failure in SSL library, usually a protocol error
error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:770 0x7f87c2fdf0:0x00000000)
If anyone can help me It will be very cool. All my apps are down and I'm fighting against this problem since yesterday morning to restore my services. I'm removing my hair one by one...
Thanks in advance.
PROBLEM SOLVED:
Hi everyone after fighting during 3 days and nights here is the final solution.
So thanks to the solution here:
How to disable SSLv3 in android for HttpsUrlConnection?
and this library: https://guardianproject.info/code/netcipher
It permits to provide to Android a better way to work with cypher and TLS in case where SSLv2 and SSlv3 are disabled.
First create this class NoSSLv3SocketFactory.java and couple this with a CypherUrl connection by creating a constructor like this
public NoSSLv3SocketFactory(URL sourceUrl) throws IOException {
this.delegate = NetCipher.getHttpsURLConnection(sourceUrl).getDefaultSSLSocketFactory();
}
NoSSLv3SocketFactory.java (complete code)
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.URL;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.net.ssl.HandshakeCompletedListener;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import info.guardianproject.netcipher.NetCipher;
public class NoSSLv3SocketFactory extends SSLSocketFactory{
private final SSLSocketFactory delegate;
public NoSSLv3SocketFactory(URL sourceUrl) throws IOException {
this.delegate = NetCipher.getHttpsURLConnection(sourceUrl).getDefaultSSLSocketFactory();
}
public NoSSLv3SocketFactory() {
this.delegate = HttpsURLConnection.getDefaultSSLSocketFactory();
}
public NoSSLv3SocketFactory(SSLSocketFactory delegate) {
this.delegate = delegate;
}
#Override
public String[] getDefaultCipherSuites() {
return delegate.getDefaultCipherSuites();
}
#Override
public String[] getSupportedCipherSuites() {
return delegate.getSupportedCipherSuites();
}
private Socket makeSocketSafe(Socket socket) {
if (socket instanceof SSLSocket) {
socket = new NoSSLv3SSLSocket((SSLSocket) socket);
}
return socket;
}
#Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return makeSocketSafe(delegate.createSocket(s, host, port, autoClose));
}
#Override
public Socket createSocket(String host, int port) throws IOException {
return makeSocketSafe(delegate.createSocket(host, port));
}
#Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
return makeSocketSafe(delegate.createSocket(host, port, localHost, localPort));
}
#Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return makeSocketSafe(delegate.createSocket(host, port));
}
#Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return makeSocketSafe(delegate.createSocket(address, port, localAddress, localPort));
}
private class NoSSLv3SSLSocket extends DelegateSSLSocket {
private NoSSLv3SSLSocket(SSLSocket delegate) {
super(delegate);
}
#Override
public void setEnabledProtocols(String[] protocols) {
if (protocols != null && protocols.length == 1 && "SSLv3".equals(protocols[0])) {
List<String> enabledProtocols = new ArrayList<String>(Arrays.asList(delegate.getEnabledProtocols()));
if (enabledProtocols.size() > 1) {
enabledProtocols.remove("SSLv3");
System.out.println("Removed SSLv3 from enabled protocols");
} else {
System.out.println("SSL stuck with protocol available for " + String.valueOf(enabledProtocols));
}
protocols = enabledProtocols.toArray(new String[enabledProtocols.size()]);
}
super.setEnabledProtocols(protocols);
}
}
public class DelegateSSLSocket extends SSLSocket {
protected final SSLSocket delegate;
DelegateSSLSocket(SSLSocket delegate) {
this.delegate = delegate;
}
#Override
public String[] getSupportedCipherSuites() {
return delegate.getSupportedCipherSuites();
}
#Override
public String[] getEnabledCipherSuites() {
return delegate.getEnabledCipherSuites();
}
#Override
public void setEnabledCipherSuites(String[] suites) {
delegate.setEnabledCipherSuites(suites);
}
#Override
public String[] getSupportedProtocols() {
return delegate.getSupportedProtocols();
}
#Override
public String[] getEnabledProtocols() {
return delegate.getEnabledProtocols();
}
#Override
public void setEnabledProtocols(String[] protocols) {
delegate.setEnabledProtocols(protocols);
}
#Override
public SSLSession getSession() {
return delegate.getSession();
}
#Override
public void addHandshakeCompletedListener(HandshakeCompletedListener listener) {
delegate.addHandshakeCompletedListener(listener);
}
#Override
public void removeHandshakeCompletedListener(HandshakeCompletedListener listener) {
delegate.removeHandshakeCompletedListener(listener);
}
#Override
public void startHandshake() throws IOException {
delegate.startHandshake();
}
#Override
public void setUseClientMode(boolean mode) {
delegate.setUseClientMode(mode);
}
#Override
public boolean getUseClientMode() {
return delegate.getUseClientMode();
}
#Override
public void setNeedClientAuth(boolean need) {
delegate.setNeedClientAuth(need);
}
#Override
public void setWantClientAuth(boolean want) {
delegate.setWantClientAuth(want);
}
#Override
public boolean getNeedClientAuth() {
return delegate.getNeedClientAuth();
}
#Override
public boolean getWantClientAuth() {
return delegate.getWantClientAuth();
}
#Override
public void setEnableSessionCreation(boolean flag) {
delegate.setEnableSessionCreation(flag);
}
#Override
public boolean getEnableSessionCreation() {
return delegate.getEnableSessionCreation();
}
#Override
public void bind(SocketAddress localAddr) throws IOException {
delegate.bind(localAddr);
}
#Override
public synchronized void close() throws IOException {
delegate.close();
}
#Override
public void connect(SocketAddress remoteAddr) throws IOException {
delegate.connect(remoteAddr);
}
#Override
public void connect(SocketAddress remoteAddr, int timeout) throws IOException {
delegate.connect(remoteAddr, timeout);
}
#Override
public SocketChannel getChannel() {
return delegate.getChannel();
}
#Override
public InetAddress getInetAddress() {
return delegate.getInetAddress();
}
#Override
public InputStream getInputStream() throws IOException {
return delegate.getInputStream();
}
#Override
public boolean getKeepAlive() throws SocketException {
return delegate.getKeepAlive();
}
#Override
public InetAddress getLocalAddress() {
return delegate.getLocalAddress();
}
#Override
public int getLocalPort() {
return delegate.getLocalPort();
}
#Override
public SocketAddress getLocalSocketAddress() {
return delegate.getLocalSocketAddress();
}
#Override
public boolean getOOBInline() throws SocketException {
return delegate.getOOBInline();
}
#Override
public OutputStream getOutputStream() throws IOException {
return delegate.getOutputStream();
}
#Override
public int getPort() {
return delegate.getPort();
}
#Override
public synchronized int getReceiveBufferSize() throws SocketException {
return delegate.getReceiveBufferSize();
}
#Override
public SocketAddress getRemoteSocketAddress() {
return delegate.getRemoteSocketAddress();
}
#Override
public boolean getReuseAddress() throws SocketException {
return delegate.getReuseAddress();
}
#Override
public synchronized int getSendBufferSize() throws SocketException {
return delegate.getSendBufferSize();
}
#Override
public int getSoLinger() throws SocketException {
return delegate.getSoLinger();
}
#Override
public synchronized int getSoTimeout() throws SocketException {
return delegate.getSoTimeout();
}
#Override
public boolean getTcpNoDelay() throws SocketException {
return delegate.getTcpNoDelay();
}
#Override
public int getTrafficClass() throws SocketException {
return delegate.getTrafficClass();
}
#Override
public boolean isBound() {
return delegate.isBound();
}
#Override
public boolean isClosed() {
return delegate.isClosed();
}
#Override
public boolean isConnected() {
return delegate.isConnected();
}
#Override
public boolean isInputShutdown() {
return delegate.isInputShutdown();
}
#Override
public boolean isOutputShutdown() {
return delegate.isOutputShutdown();
}
#Override
public void sendUrgentData(int value) throws IOException {
delegate.sendUrgentData(value);
}
#Override
public void setKeepAlive(boolean keepAlive) throws SocketException {
delegate.setKeepAlive(keepAlive);
}
#Override
public void setOOBInline(boolean oobinline) throws SocketException {
delegate.setOOBInline(oobinline);
}
#Override
public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {
delegate.setPerformancePreferences(connectionTime, latency, bandwidth);
}
#Override
public synchronized void setReceiveBufferSize(int size) throws SocketException {
delegate.setReceiveBufferSize(size);
}
#Override
public void setReuseAddress(boolean reuse) throws SocketException {
delegate.setReuseAddress(reuse);
}
#Override
public synchronized void setSendBufferSize(int size) throws SocketException {
delegate.setSendBufferSize(size);
}
#Override
public void setSoLinger(boolean on, int timeout) throws SocketException {
delegate.setSoLinger(on, timeout);
}
#Override
public synchronized void setSoTimeout(int timeout) throws SocketException {
delegate.setSoTimeout(timeout);
}
#Override
public void setTcpNoDelay(boolean on) throws SocketException {
delegate.setTcpNoDelay(on);
}
#Override
public void setTrafficClass(int value) throws SocketException {
delegate.setTrafficClass(value);
}
#Override
public void shutdownInput() throws IOException {
delegate.shutdownInput();
}
#Override
public void shutdownOutput() throws IOException {
delegate.shutdownOutput();
}
#Override
public String toString() {
return delegate.toString();
}
#Override
public boolean equals(Object o) {
return delegate.equals(o);
}
}
}
and now (in my case with retrofit) just use it like this:
So first, Add a static method (or as you want create it on use) to make a okHttpClient with our previously created NoSSlv3Factory.java class.
public static OkClient createClient(int readTimeout, TimeUnit readTimeoutUnit, int connectTimeout, TimeUnit connectTimeoutUnit)
{
final OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setReadTimeout(readTimeout, readTimeoutUnit);
okHttpClient.setConnectTimeout(connectTimeout, connectTimeoutUnit);
try {
URL url = new URL(ApiIntentService.getHostAddress());
SSLSocketFactory NoSSLv3Factory = new NoSSLv3SocketFactory(url);
okHttpClient.setSslSocketFactory(NoSSLv3Factory);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return new OkClient(okHttpClient);
}
Then, in my case when you create your RestAdapter just make it like this, and don't forget to set you client.
public class LoginRestClient
{
private static final String BASE_URL = "";
private LoginApiService apiService;
public LoginRestClient()
{
Gson gson = new GsonBuilder()
.setDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'")
.create();
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint(ApiIntentService.getHostAddress())
.setConverter(new GsonConverter(gson))
.setClient(ApiIntentService.createClient(60, TimeUnit.SECONDS, 20, TimeUnit.SECONDS))
.build();
apiService = restAdapter.create(LoginApiService.class);
}
public LoginApiService getApiService() {
return apiService;
}
}
With this it should be working.
I hope it will be usefull for someone else.
I found the solution here in this link.
You just have to place below code in your Android application class. And that is enough. Don't need to do any changes in your Retrofit settings. It saved my day.
public class MyApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
try {
// Google Play will install latest OpenSSL
ProviderInstaller.installIfNeeded(getApplicationContext());
SSLContext sslContext;
sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, null, null);
sslContext.createSSLEngine();
} catch (GooglePlayServicesRepairableException | GooglePlayServicesNotAvailableException
| NoSuchAlgorithmException | KeyManagementException e) {
e.printStackTrace();
}
}
}
Hope this will be of help. Thank you.
If you are using OkHttpClient use
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.connectionSpecs(Arrays.asList(ConnectionSpec.COMPATIBLE_TLS));
And the do client.build() when setting your client.
Check if you have included https:// instead of sending http:// to your server

How to receive message without using createChat for android XMPP chat smack api

Hi I am confused with the logic of implementing chatManagerListener interface inside a Service.
Below is my service code:
public class MyService3 extends Service {
ChatManager chatManager;
ChatManagerListener chatManagerListener;
AbstractXMPPConnection abstractXMPPConnection;
MyXmpp2 myXmpp2;
public MyService3() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("Myservice3:","Started");
abstractXMPPConnection = myXmpp2.getConnection();
abstractXMPPConnection.addConnectionListener(new ConnectionListener() {
#Override
public void connected(XMPPConnection connection) {
Log.d("XMPPConnection:","connected");
}
#Override
public void authenticated(XMPPConnection connection, boolean resumed) {
Log.d("XMPPConnection:","authenticated");
//Once authenticated start listening for messages
}
#Override
public void connectionClosed() {
Log.d("XMPPConnection:","connectionClosed");
}
#Override
public void connectionClosedOnError(Exception e) {
Log.d("XMPPConnection:","connectionClosedOnError");
}
#Override
public void reconnectionSuccessful() {
Log.d("XMPPConnection:","reconnectionSuccessful");
}
#Override
public void reconnectingIn(int seconds) {
Log.d("XMPPConnection:","reconnectingIn");
}
#Override
public void reconnectionFailed(Exception e) {
Log.d("XMPPConnection:","reconnectionFailed");
}
});
Log.d("isOnline:", myXmpp2.getConnection().isConnected() + "");
chatManager = ChatManager.getInstanceFor(abstractXMPPConnection);
chatManager.addChatListener(chatManagerListener);
chatManagerListener = new ChatManagerListener() {
#Override
public void chatCreated(Chat chat, boolean createdLocally) {
chat.addMessageListener(new ChatMessageListener() {
#Override
public void processMessage(Chat chat, Message message) {
Log.d("Hello::","World");
//NOT WORKNIG
if(message.getBody()!=null)
{
Log.d("Message::",message.getBody());
}
}
});
}
};
return super.onStartCommand(intent, flags, startId);
}
}
Whenever is send a packet i am getting this following exception .I don't kno why its arising
Exception in packet listener java.lang.NullPointerException: Attempt to invoke interface method 'void org.jivesoftware.smack.chat.ChatManagerListener.chatCreated(org.jivesoftware.smack.chat.Chat, boolean)' on a null object reference
at org.jivesoftware.smack.chat.ChatManager.createChat(ChatManager.java:255)
at org.jivesoftware.smack.chat.ChatManager.createChat(ChatManager.java:287)
In simple terms i want to know how to implement ChatMessage listener in the service.Please be kind
You need to createchat once you successfully connected & authenticated
Once you got the instance of ChatManager.For package transmission you need to createchat with peer/group check this link for method to createchat.
chatManager = ChatManager.getInstanceFor(abstractXMPPConnection);
newChat = chatmanager.createChat(userid, chatManagerListener);
once you get the Chat instance you can send package & retrive on your chatmanagerListner
from newChat you can sendMessage
To get Package (message, chat)
You can try below code if your connection/authentication process is done successfully than
final Chat newChat = ChatManager.getInstanceFor(xmppConn).createChat(userJid, new MessageListener() {
#Override
public void processMessage(final Chat arg0, final Message arg1) {
LOG.info("Sent message: " + arg1.getBody());
}
});
try {
final Message message = new Message();
message.setFrom(chatProperties.getDomain());
message.setTo(userJid);
message.setType(Type.normal);
message.setBody(text);
message.setSubject("");
newChat.sendMessage(message);
xmppConn.disconnect();
} catch (final Exception e) {
LOG.error("Error while sending message to " + userName + ": ", e);
}
UPDATE
You can try using PacketListener.
XMPPConnection's addPacketListener method check this link for details.
Add PacketListener to XMPPConnection with PacketFilter type Message
But before adding packetlistner remove if already added any instance in xmppconnection.
Check below code
private PacketListener packetListener = new PacketListener() {
#Override
public void processPacket(Packet packet) {
if (packet instanceof Message) {
Message message = (Message) packet;
String chatMessage = message.getBody();
}
}
};
private void regiSterPackateListner() {
PacketTypeFilter filter = new PacketTypeFilter(Message.class);
try {
if (packetListener != null) {
//Avoid adding multiple packetlistner
abstractXMPPConnection.removePacketListener(packetListener);
}
abstractXMPPConnection.addPacketListener(packetListener, filter);
} catch (Exception e) {
e.printStackTrace();
}
}
Refer to this example:
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
public class GoogleTalkDemo extends Thread{
private XMPPConnection xmppConnection;
public void connect(String server, int port, String s) throws Exception {
xmppConnection = new XMPPConnection(new ConnectionConfiguration(server, port,s));
xmppConnection.connect();
}
public void disconnect(){
if(xmppConnection != null){
xmppConnection.disconnect();
interrupt();
}
}
public void login(String username, String password) throws Exception{
connect("talk.google.com", 5222, "gmail.com");
xmppConnection.login(username, password);
}
public void run(){
try {
login("youtID#sample.com", "your password");
System.out.println("Login successful");
listeningForMessages();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String args[]) throws Exception {
GoogleTalkDemo gtd = new GoogleTalkDemo();
gtd.run();
}
public void listeningForMessages() {
PacketFilter filter = new AndFilter(new PacketTypeFilter(Message.class));
PacketCollector collector = xmppConnection.createPacketCollector(filter);
while (true) {
Packet packet = collector.nextResult();
if (packet instanceof Message) {
Message message = (Message) packet;
if (message != null && message.getBody() != null)
System.out.println("Received message from "
+ packet.getFrom() + " : "
+ (message != null ? message.getBody() : "NULL"));
}
}
}
}
Hope it will help you.
A simple demo about sending and receiving masseges:
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManager;
import org.jivesoftware.smack.ChatManagerListener;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
public class Test {
public static void main(String args[]) throws XMPPException {
ConnectionConfiguration config = new ConnectionConfiguration("127.0.0.1", 5222);
XMPPConnection connection = new XMPPConnection(config);
connection.connect();
connection.login("userx", "123456");
ChatManager cm = connection.getChatManager();
Chat chat = cm.createChat("tongqian#tsw-PC", null);
/*
* add listener
*/
cm.addChatListener(new ChatManagerListener() {
#Override
public void chatCreated(Chat chat, boolean create) {
chat.addMessageListener(new MessageListener() {
#Override
public void processMessage(Chat chat, Message msg) {
System.out.println(chat.getParticipant() + ":" + msg.getBody());
}
});
}
});
chat.sendMessage("hello");
while(true);
//connection.disconnect();
}
}

Netty - Client/Server chat

I need to have a client/server communication in netty for one of my project purpose. So I just started with a handsOn to improve from that.I am learning netty and I am a beginner in that.
I have tried a simple client server chatting with netty.
The client and server is getting initialized and I could see the server is able to get the Client pipeline for connection establishment, but when the client sends the message, it is not getting inside the messageReceived part of the ServerAdapterHandler. Below are my source codes,
CLIENT:
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
public class ContainerClient {
String server;
int port;
int containerPort;
public ContainerClient(String server, int port, int containerPort) {
this.server = server;
this.port = port;
this.containerPort = containerPort;
}
public static void main(String[] args) {
String server = "localhost";
int port = 5252;
int containerPort = 8094;
new ContainerClient(server, port, containerPort).start();
}
public void start() {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap().group(group)
.channel(NioSocketChannel.class)
.handler(new ClientAdapterInitializer());
Channel channel = bootstrap.connect(server, port).sync().channel();
channel.write("Hi\n");
channel.write("Hi\n");
channel.write("Hi\n");
} catch (Exception e) {
e.printStackTrace();
} finally {
group.shutdownGracefully();
}
}
}
CLIENT CHANNEL INITIALIZER:
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
public class ClientAdapterInitializer extends ChannelInitializer<SocketChannel> {
#Override
protected void initChannel(SocketChannel channel) throws Exception {
ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("handler", new ClientAdapterHandler());
}
}
CLIENT MESSAGE HANDLER:
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
public class ClientAdapterHandler extends
ChannelInboundMessageHandlerAdapter<String> {
#Override
public void messageReceived(ChannelHandlerContext context, String message)
throws Exception {
System.out.println(message);
if (message.equals("quit"))
throw new ServerEndedException("Server is closed");
}
#Override
public void channelRead(ChannelHandlerContext arg0, Object arg1)
throws Exception {
// TODO Auto-generated method stub
}
#Override
public void channelReadComplete(ChannelHandlerContext arg0)
throws Exception {
// TODO Auto-generated method stub
}
#Override
public void channelWritabilityChanged(ChannelHandlerContext arg0)
throws Exception {
// TODO Auto-generated method stub
}
}
SERVER:
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class ContainerServer {
int port;
public static void main(String[] args) {
new ContainerServer().start();
}
public void start() {
port = 5252;
EventLoopGroup producer = new NioEventLoopGroup();
EventLoopGroup consumer = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap()
.group(producer, consumer)
.channel(NioServerSocketChannel.class)
.childHandler(new ServerAdapterInitializer());
System.out.println("Server started");
bootstrap.bind(port).sync().channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
producer.shutdownGracefully();
consumer.shutdownGracefully();
}
}
}
SERVER CHANNEL INITIALIZER:
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
public class ServerAdapterInitializer extends ChannelInitializer<SocketChannel> {
#Override
protected void initChannel(SocketChannel channel) throws Exception {
ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("handler", new ServerAdapterHandler());
}
}
SERVER MESSAGE HANDLER:
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
public class ServerAdapterHandler extends
ChannelInboundMessageHandlerAdapter<String> {
private static final ChannelGroup channels = new DefaultChannelGroup(
"containers", GlobalEventExecutor.INSTANCE);
#Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
System.out.println("[START] New Container has been initialzed");
channels.add(ctx.channel());
super.handlerAdded(ctx);
}
#Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
System.out.println("[END] A Container has been removed");
channels.remove(ctx.channel());
super.handlerRemoved(ctx);
}
#Override
public void messageReceived(ChannelHandlerContext ctx, String arg1)
throws Exception {
Channel currentChannel = ctx.channel();
System.out.println("[INFO] - " + currentChannel.remoteAddress() + " - "
+ arg1);
currentChannel.write("[Server] - Success");
}
#Override
public boolean beginMessageReceived(ChannelHandlerContext ctx)
throws Exception {
System.out.println("Message received");
return super.beginMessageReceived(ctx);
}
#Override
public void channelRead(ChannelHandlerContext arg0, Object arg1)
throws Exception {
System.out.println("channelRead");
}
#Override
public void channelReadComplete(ChannelHandlerContext arg0)
throws Exception {
// TODO Auto-generated method stub
System.out.println("channelReadComplete");
}
#Override
public void channelWritabilityChanged(ChannelHandlerContext arg0)
throws Exception {
// TODO Auto-generated method stub
System.out.println("channelWritabilityChanged");
}
}
Below is the output I am getting in server and nothing in client:
Server started
[START] New Container has been initialzed
channelReadComplete
[END] A Container has been removed
But The expected should be,
Server started
[START] New Container has been initialzed
channelReadComplete
[INFO] - localhost - Hi
[INFO] - localhost - Hi
[INFO] - localhost - Hi
[END] A Container has been removed
And I should get response in client as,
[Server] - Success
[Server] - Success
[Server] - Success
I tried with line Delimter in framer also, but same results.
Someone could you please help on this?
Thanks in advance!!.
It works for me with the following change to the start method in your ContainerClient. Just add a channel.flush().
public void start() {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap().group(group).channel(NioSocketChannel.class).handler(new ClientAdapterInitializer());
Channel channel = bootstrap.connect(server, port).sync().channel();
channel.write("Hi\n");
channel.write("Hi\n");
channel.write("Hi\n");
channel.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
group.shutdownGracefully();
}
}
The ChannelInboundMessageHandlerAdapter does not exist anymore in newer version of 4.0. I used a SimpleChannelInboundHandler.
public class ServerAdapterHandler extends SimpleChannelInboundHandler<String> {
#Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
Channel currentChannel = ctx.channel();
System.out.println("[INFO] - " + currentChannel.remoteAddress() + " - " + msg);
currentChannel.write("[Server] - Success");
}
}

How to be notified when a SocketChannel is closed?

I want to be notified when a SocketChannel has its close method called. My first thought was to create a wrapper which notifies a listener when the implCloseSelectableChannel method is called (since the close method itself is declared final in AbstractInterruptibleChannel). This solution works, but when I tried to register it with a Selector I would get an IllegalSelectorException because of the following check in SelectorImpl:
/* */ protected final SelectionKey register(AbstractSelectableChannel paramAbstractSelectableChannel, int paramInt, Object paramObject)
/* */ {
/* 128 */ if (!(paramAbstractSelectableChannel instanceof SelChImpl))
/* 129 */ throw new IllegalSelectorException();
Now I can't override the register method to delegate to the wrapped SocketChannel because it's declared final in AbstractSelectableChannel and I can't implement SelChImpl because it has default visibility in the sun.nio.ch package. The only way I can see to proceed from here would be to make my own SelectorProvider and Selector, but that seems like overkill for something so simple.
Is there an easier way to be notified when a SocketChannel has been closed or do I need to rethink my program design?
SocketChannelWrapper example:
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketOption;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
public class SocketChannelWrapper extends SocketChannel {
private static interface CloseListener {
public void socketChannelClosed(SocketChannel channel);
}
private final SocketChannel socket;
private final CloseListener listener;
public SocketChannelWrapper(SocketChannel socket, CloseListener l) {
super(socket.provider());
this.socket = socket;
listener = l;
}
#Override
public SocketAddress getLocalAddress() throws IOException {
return socket.getLocalAddress();
}
#Override
public <T> T getOption(SocketOption<T> name) throws IOException {
return socket.getOption(name);
}
#Override
public Set<SocketOption<?>> supportedOptions() {
return socket.supportedOptions();
}
#Override
public SocketChannel bind(SocketAddress local) throws IOException {
return socket.bind(local);
}
#Override
public <T> SocketChannel setOption(SocketOption<T> name, T value)
throws IOException {
return socket.setOption(name, value);
}
#Override
public SocketChannel shutdownInput() throws IOException {
return socket.shutdownInput();
}
#Override
public SocketChannel shutdownOutput() throws IOException {
return socket.shutdownOutput();
}
#Override
public Socket socket() {
return socket.socket();
}
#Override
public boolean isConnected() {
return socket.isConnected();
}
#Override
public boolean isConnectionPending() {
return socket.isConnectionPending();
}
#Override
public boolean connect(SocketAddress remote) throws IOException {
return socket.connect(remote);
}
#Override
public boolean finishConnect() throws IOException {
return socket.finishConnect();
}
#Override
public SocketAddress getRemoteAddress() throws IOException {
return socket.getRemoteAddress();
}
#Override
public int read(ByteBuffer dst) throws IOException {
return socket.read(dst);
}
#Override
public long read(ByteBuffer[] dsts, int offset, int length)
throws IOException {
return socket.read(dsts, offset, length);
}
#Override
public int write(ByteBuffer src) throws IOException {
return socket.write(src);
}
#Override
public long write(ByteBuffer[] srcs, int offset, int length)
throws IOException {
return socket.write(srcs, offset, length);
}
#Override
protected void implCloseSelectableChannel() throws IOException {
socket.close();
listener.socketChannelClosed(this);
}
#Override
protected void implConfigureBlocking(boolean block) throws IOException {
socket.configureBlocking(block);
}
public static void main(String[] args) throws UnknownHostException,
IOException {
final Selector selector = Selector.open();
Thread t = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
selector.select();
Iterator<SelectionKey> itr = selector.selectedKeys()
.iterator();
while (itr.hasNext()) {
SelectionKey key = itr.next();
itr.remove();
if (key.isValid()) {
if (key.isAcceptable()) {
((ServerSocketChannel) key.channel())
.accept();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
t.setDaemon(true);
ServerSocketChannel server = ServerSocketChannel.open().bind(
new InetSocketAddress(1234));
server.configureBlocking(false);
server.register(selector, SelectionKey.OP_ACCEPT);
t.start();
SocketChannel socket = new SocketChannelWrapper(
SocketChannel.open(new InetSocketAddress(InetAddress
.getLocalHost(), 1234)), new CloseListener() {
#Override
public void socketChannelClosed(SocketChannel channel) {
System.out.println("Socket closed!");
}
});
socket.configureBlocking(false);
// socket.close(); //prints out "Socket closed!"
socket.register(selector, SelectionKey.OP_READ);
}
}
If the SocketChannel is closed by you, you are closing it, so you can notify yourself any way you like.
If you want to be notified when the peer closes the connection,, OP_READ will fire and a read will return -1.
that's nasty. you could maybe use a byte level aop package like http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/ (with aop you can should be able to add a cutpoint on the close method that does your callback).
you could also create a package with the same name as the sun package and implement the inteface in there.
but i can't see a good, clean way to do this.

Categories

Resources