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");
}
}
Related
I hope to realize the following communication among three parties:
The communication process is:
(1) A sends M1 to B
(2) B, after receiving M1, forwards to C
(3) C, after receiving M1, responds with M2
(4) B, after receiving M2, forward M2 to A
(5) Finally A output M2
I have realized all the code using Netty, but currently the problem is:
after B receiving M2 from C, I tried to put M2 to the communication channel between A and B, hoping that A can directly receive it, but it seems it fails. Thanks in advance if anyone can help, and the following is a basic implementation of my code:
A.java sends M1 to B, and AHandler.java listens on what sent by B:
// A.java
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
public class A {
public static void main(String[] args) {
// loop group
EventLoopGroup loopGroup = new NioEventLoopGroup();
// create bootstrap
Bootstrap bootstrap = new Bootstrap();
try {
bootstrap.group(loopGroup)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
#Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new AHandler());
}
});
ChannelFuture future = bootstrap.connect("localhost", 6002).sync();
future.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
loopGroup.shutdownGracefully();
}
}
}
// AHandler.java
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.util.CharsetUtil;
public class AHandler extends ChannelInboundHandlerAdapter {
#Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
String M1 = "M1";
ctx.writeAndFlush(Unpooled.copiedBuffer(M1, CharsetUtil.UTF_8));
}
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// !!! Hope to receive what B forwards from C, namely M2, but cannot receive it
ByteBuf buf = (ByteBuf) msg;
System.out.println("B responds receipt: " + buf.toString(CharsetUtil.UTF_8));
}
}
B listens on port 6002, and after receiving M1 from A, forwards to C by creating a new channel between B and C:
// B.java
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class B {
public static void main(String[] args) {
// create thread pool
// create Boss group : receiving client connection
EventLoopGroup bossGroup = new NioEventLoopGroup();
// create work group: network read and communication
EventLoopGroup workGroup = new NioEventLoopGroup();
// create start class
ServerBootstrap bootstrap = new ServerBootstrap();
try {
bootstrap.group(bossGroup, workGroup) // set thread group
.channel(NioServerSocketChannel.class) //set channel
.option(ChannelOption.SO_BACKLOG, 1024) // set the number of thread connections
//.option(ChannelOption.SO_KEEPALIVE, true) // keep connection
.childHandler(new ChannelInitializer<SocketChannel>() {
#Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new BHandler());
}
}).childOption(ChannelOption.SO_KEEPALIVE, true);
System.out.println("----- B is online -----");
ChannelFuture channelFuture = bootstrap.bind(6002).sync();
channelFuture.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
}
// BHandler.java (as the server end between A and B)
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.CharsetUtil;
import io.netty.util.concurrent.GlobalEventExecutor;
public class BHandler extends ChannelInboundHandlerAdapter {
public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
public static Channel Channel_AB = null;
public void BForwardM1() {
EventLoopGroup loopGroup = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
try {
bootstrap.group(loopGroup)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
#Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new BCHandler());
}
});
ChannelFuture future = bootstrap.connect("localhost", 6003).sync();
future.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
loopGroup.shutdownGracefully();
}
}
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// Add channel_AB to channel group
Channel channel_AB = ctx.channel();
Channel_AB = channel_AB;
channelGroup.add(channel_AB);
System.out.println("Received from A: " + channel_AB.remoteAddress() + ", channel ID: " + channel_AB.id());
ByteBuf buf = (ByteBuf) msg;
String M1_From_A = buf.toString(CharsetUtil.UTF_8);
System.out.println("M1_From_A: " + M1_From_A);
}
#Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// B forwards M1 to C
BForwardM1();
}
}
// BCHandler.java (as the client end of between B and C)
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.util.CharsetUtil;
public class BCHandler extends ChannelInboundHandlerAdapter{
#Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
String M1 = "M1";
// B forwards M1 to C
ctx.writeAndFlush(Unpooled.copiedBuffer(M1, CharsetUtil.UTF_8));
}
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = (ByteBuf) msg;
// C responds with M2
String M2 = buf.toString(CharsetUtil.UTF_8);
System.out.println("Receive C's respond: " + M2);
// !!! Trying to put M2 to AB's channel
BHandler.channelGroup.forEach(ch -> {
if (ch != null) {
ch.writeAndFlush(Unpooled.copiedBuffer(M2, CharsetUtil.UTF_8));
} else {
System.out.println("No available channel");
}
});
}
}
C listens on the port 6003, and responds B with message M2:
// C.java
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class C {
public static void main(String[] args) {
// create Boss group : receiving client connection
EventLoopGroup bossGroup = new NioEventLoopGroup();
// create work group: network read and communication
EventLoopGroup workGroup = new NioEventLoopGroup();
// create start class
ServerBootstrap bootstrap = new ServerBootstrap();
try {
bootstrap.group(bossGroup, workGroup) // set thread group
.channel(NioServerSocketChannel.class) //set channel
.option(ChannelOption.SO_BACKLOG, 1024) // set the number of thread connections
.childHandler(new ChannelInitializer<SocketChannel>() {
#Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new CHandler());
}
});
System.out.println("----- C is online -----");
ChannelFuture channelFuture = bootstrap.bind(6003).sync();
channelFuture.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
}
// CHandler.java
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
public class CHandler extends ChannelInboundHandlerAdapter {
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = (ByteBuf) msg;
System.out.println("Receive from B: " + buf.toString(CharsetUtil.UTF_8));
}
#Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// C responds with M2
ctx.writeAndFlush(Unpooled.copiedBuffer("M2", CharsetUtil.UTF_8));
}
}
My idea is to pass the AB channel context to the BCHandler.java, which receives the response from C, and then uses the AB channel to send back to A, but it seems that A cannot receive the M2 at the end. Thanks a lot if you can provide help!
Essentially what needs to be realized is a Proxy Server using Netty, so this example can solve the problem and it works for me.
I'm opening a simple tcp server, but netty client can't connect.
if necessary
(netty client) <-----> (netty server) it works
(simple tcp client) <-----> (simple tcp server) it works
but
(netty client) <----> (simple tcp server) doesn't work
can you help me
public class TCPServer extends Thread {
private ServerSocket serverSocket;
public TCPServer(int port) throws IOException {
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(10000);
}
public void run() {
while(true) {
try {
System.out.println("Waiting for client on port " +
serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Just connected to " + server.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(server.getInputStream());
System.out.println(in.readUTF());
DataOutputStream out = new DataOutputStream(server.getOutputStream());
out.writeUTF("Thank you for connecting to " + server.getLocalSocketAddress()
+ "\nGoodbye!");
// server.close();
} catch (SocketTimeoutException s) {
System.out.println("Socket timed out!");
// break;
} catch (IOException e) {
e.printStackTrace();
// break;
}
}
}
public static void main(String [] args) {
int port = 14115;
try {
Thread t = new TCPServer(port);
t.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
---Client----
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
public final class Client {
static final String HOST = System.getProperty("host", "127.0.0.1");
static final int PORT = Integer.parseInt(System.getProperty("port", "14115"));
public static void main(String[] args) throws Exception {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group);
b.channel(NioSocketChannel.class);
b.handler(new ChannelInitializer<SocketChannel>() {
#Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(new StringDecoder());
p.addLast(new StringDecoder());
p.addLast(new ClientHandler());
}
});
b.option(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture f = b.connect(HOST, PORT).sync();
} finally {
group.shutdownGracefully();
}
}
}
---Client Handler---
public class ClientHandler extends ChannelInboundHandlerAdapter {
public ClientHandler() {
}
#Override
public void channelActive(ChannelHandlerContext ctx) {
System.out.println("Channel Active");
try {
ctx.writeAndFlush("Hello Server");
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
System.out.println("client received: " + msg);
ctx.writeAndFlush(msg);
}
#Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
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();
}
}
We are trying to create a system using Javas RMI. The problem is that a maintained list on the client cannot be accessed from the server using Java RMI. It seems that the RMI connection is handling a copy of the initialized list.
Below is a minimal example using an integer that the client increments every second until it equals 10. The server receives 0 all the time though.
Anyone have any idea what we are doing wrong?
Just run server and the client as a java application.
ServerDefaultImpl.java
package rmi;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
public class ServerDefaultImpl implements EIServerRemote, Runnable {
ClientRemote client;
private boolean running = true;
public ServerDefaultImpl() {
try {
LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
ServerDefaultImpl server = this;
EIServerRemote stub = (EIServerRemote) UnicastRemoteObject.exportObject(server, 0);
Registry registry = LocateRegistry.getRegistry();
registry.rebind("test", stub);
} catch (RemoteException e) {
e.printStackTrace();
}
new Thread(this).start();
}
public static void main(String[] args) {
new ServerDefaultImpl();
}
#Override
public void run() {
while (true == running) {
try {
Thread.sleep(1000);
if (null != client) { //Client not connected yet.
int test = client.test();
System.out.println(test);
running = test <= 10;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public void attachClientListener(ClientRemote client) throws RemoteException {
this.client = client;
}
}
EIServerRemote.java
package rmi;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface EIServerRemote extends Remote {
void attachClientListener(ClientRemote client) throws RemoteException;
}
ClientRemote.java
package rmi;
import java.io.Serializable;
import java.rmi.Remote;
public interface ClientRemote extends Remote,Serializable {
int test();
}
ClientDefaultImpl.java
package rmi;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class ClientDefaultImpl implements Runnable,
ClientRemote {
private static final long serialVersionUID = 4846141863099303590L;
protected EIServerRemote server = null;
public int test;
public boolean running = true;
public ClientDefaultImpl(String serverName) {
test = 0;
try {
connect(serverName);
} catch (RemoteException | NotBoundException e) {
e.printStackTrace();
}
new Thread(this).start();
}
public static void main(String[] args) {
new ClientDefaultImpl("test");
}
public void connect(String serverName) throws RemoteException,
NotBoundException {
Registry registry = LocateRegistry.getRegistry();
EIServerRemote s = (EIServerRemote) registry.lookup(serverName);
server = s;
s.attachClientListener((ClientRemote) this);
}
#Override
public void run() {
while (true == running) {
try {
Thread.sleep(1000);
System.out.println(test++);
running = test <= 10;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public int test() {
return test;
}
}
It seems that the RMI connection is handling a copy of the initialized list.
That's correct. The list isn't a remote object, so it is passed and returned via serialization.
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.