Netty RtspEncoder/Decoder issue - java

To develop RtspClient(just message transaction, not playing video), I thought that I will use Netty, and I have created the classes as follow,(rtsp is creating toooo much problem to me, I don't know, is this because lag of knowledge? any-how...),
TestRtspClient.java
public class TestRtspClient {
private final String host;
private final int port;
public TestRtspClient(String host, int port) {
this.host = host;
this.port = port;
}
public void start() throws Exception {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group);
bootstrap.channel(NioSocketChannel.class);
bootstrap.handler(new TestRtspClientInitializer());
Channel channel = bootstrap.connect(host, port).sync().channel();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//DESCRIBE rtsp://192.168.1.26:8554/nature.ts RTSP/1.0\r\nCSeq: 3\r\n\r\n
while(true) {
channel.write(br.readLine() + "\r\n");
channel.flush();
}
} finally {
group.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
new TestRtspClient("192.168.1.26", 8554).start();
}
}
and here is TestRtspClientInitializer.java
public class TestRtspClientInitializer extends ChannelInitializer<SocketChannel> {
#Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipe = ch.pipeline();
// pipe.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
// pipe.addLast("decoder", new StringDecoder());
// pipe.addLast("encoder", new StringEncoder());
// pipe.addLast("encoder", new RtspRequestEncoder());
// pipe.addLast("decoder", new RtspResponseDecoder());
pipe.addLast("encoder", new HttpRequestEncoder());
pipe.addLast("decoder", new HttpResponseDecoder());
pipe.addLast("handler", new TestRtspClientHandler());
}
}
and here is TestRtspClientHandler.java
public class TestRtspClientHandler extends ChannelInboundMessageHandlerAdapter<HttpObject> {
#Override
public void messageReceived(ChannelHandlerContext ctx, String msg) throws Exception {
if(msg instanceof HttpResponse) {
System.out.println("Rtsp Response");
} else if(msg instanceof HttpRequest) {
System.out.println("Rtsp Request");
} else {
System.err.println("not supported format");
}
}
}
and I am using Live555MediaServer as RtspServer and Netty 4.0.0.CR3. When I am using DelimiterBasedFrameDecoder with stringdecoder and encoder its working fine, but If I use RtspRequest/Response encoder/decoder I am getting following warning, and no msg will be sent to L555.(also same with HttpReq/Resp encoder and decoder)
passing this as commandline arg in eclipse
DESCRIBE rtsp://192.168.1.26:8554/nature.ts RTSP/1.0\r\nCSeq: 3\r\n
Mar 25, 2014 6:45:28 PM
io.netty.channel.DefaultChannelPipeline$ByteHeadHandler flush WARNING:
Discarded 1 outbound message(s) that reached at the head of the
pipeline. Please check your pipeline configuration.
Help me to fix this issue, and also explain me in-brief what is wrong in this code modules.
Thank You.

First of all, please upgrade to the latest Netty 4.0.x version.
Because you specified <String> when you extend ChannelInboundMessageHandlerAdapter in your TestRtspClientHandler, it will only receive a message whose type is String, which is not the case. You have to use HttpObject instead of String.

Related

Mina usage of DatagramConnector does not work

I have a tcp client, which is based on the mina (V2.0.21 and J8) framework. It is working fine.
Here is the minimal example:
private static IoConnector connector;
public static void main(String[] args) throws InterruptedException {
connector = new NioSocketConnector();
connector.getFilterChain().addLast( "logger", new LoggingFilter() );
connector.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));
connector.setHandler(new Handler());
try {
ConnectFuture connFuture = connector.connect(new InetSocketAddress("x.x.x.x", 9999));
connFuture.awaitUninterruptibly();
connFuture.getSession();
} catch (Exception e) {
System.err.println(e);
}
while(true) {
System.out.println("sleep.");
Thread.sleep(3000);
}
}
This is my handler:
public class Handler implements IoHandler {
#Override
public void messageReceived(IoSession session, Object message) throws Exception {
String str = (String)message;
System.out.println("->" + str);
}
#Override
public void sessionCreated(IoSession session) throws Exception {
System.out.println("CREATED.");
}
#Override
public void sessionOpened(IoSession session) throws Exception {
System.out.println("OPENED.");
}
...
}
Now, i have changed the line
connector = new NioSocketConnector();
to
connector = new NioDatagramConnector();
to be able to receive data via UDP.
If i now send packages via UDP (e.g. using a network test tool) to the port 9999 this program will not receive anything anymore. But i can see the log information, that the session was opened and created. Can somebody explain, why UDP is not working (to be more specific: messageReceived() is not called), but TCP does?
UPDATE: As a test tool i am using this method here:
public static void main(String[] args) throws IOException {
InetAddress ia = InetAddress.getByName("x.x.x.x");
int port = 9999;
String s = "Message";
byte[] data = s.getBytes();
DatagramPacket packet = new DatagramPacket( data, data.length, ia, port );
DatagramSocket toSocket = new DatagramSocket();
toSocket.send( packet );
toSocket.close();
System.out.println("Send.");
}
Thanks
Ok, the secret is to know, that in UDP case both, the "connector" and "acceptor" side is handled by the class NioDatagramAcceptor.
This piece of code does the magic for the UDP-"connector"-side:
NioDatagramAcceptor acceptor = new NioDatagramAcceptor();
acceptor.getFilterChain().addLast( "logger", new LoggingFilter() );
acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));
acceptor.setHandler(new Handler());
acceptor.bind(new InetSocketAddress(9999));

SimpleChannelInboundHandler never fires channelRead0

on some day i decided to create a Netty Chat server using Tcp protocol. Currently, it successfully logging connect and disconnect, but channelRead0 in my handler is never fires. I tried Python client.
Netty version: 4.1.6.Final
Handler code:
public class ServerWrapperHandler extends SimpleChannelInboundHandler<String> {
private final TcpServer server;
public ServerWrapperHandler(TcpServer server){
this.server = server;
}
#Override
public void handlerAdded(ChannelHandlerContext ctx) {
System.out.println("Client connected.");
server.addClient(ctx);
}
#Override
public void handlerRemoved(ChannelHandlerContext ctx) {
System.out.println("Client disconnected.");
server.removeClient(ctx);
}
#Override
public void channelRead0(ChannelHandlerContext ctx, String msg) {
System.out.println("Message received.");
server.handleMessage(ctx, msg);
}
#Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
System.out.println("Read complete.");
super.channelReadComplete(ctx);
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
Output:
[TCPServ] Starting on 0.0.0.0:1052
Client connected.
Read complete.
Read complete.
Client disconnected.
Client code:
import socket
conn = socket.socket()
conn.connect(("127.0.0.1", 1052))
conn.send("Hello")
tmp = conn.recv(1024)
while tmp:
data += tmp
tmp = conn.recv(1024)
print(data.decode("utf-8"))
conn.close()
Btw, the problem was in my initializer: i added DelimiterBasedFrameDecoder to my pipeline, and this decoder is stopping the thread. I dont know why, but i dont needed this decoder, so i just deleted it, and everything started to work.
#Override
protected void initChannel(SocketChannel ch) throws Exception {
// Create a default pipeline implementation.
ChannelPipeline pipeline = ch.pipeline();
// Protocol Decoder - translates binary data (e.g. ByteBuf) into a Java object.
// Protocol Encoder - translates a Java object into binary data.
// Add the text line codec combination first,
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); //<--- DELETE THIS
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("handler", new ServerWrapperHandler(tcpServer));
}

Netty client fail to read response from non-netty server

I have a Tcp client that connect to a old mainframe (52 years) that send and receive request and response from it.
Here is core connection part of the my client ,
public class SimpleConnector {
private String carrier;
private SocketChannel socketChannel;
public static final byte END_OF_MESSAGE_BYTE = (byte) 0x2b;
public SimpleConnector(String carrier, InetSocketAddress inetSocketAddress) throws IOException {
this.carrier = this.carrier;
socketChannel = SocketChannel.open();
socketChannel.socket().connect(inetSocketAddress, 30000);
}
public void shutDown() throws IOException {
this.socketChannel.close();
}
//Send Request
public String sendRequest(String request) throws Exception {
final CharsetEncoder charsetEncoder = Charset.forName("ISO-8859-1").newEncoder();
int requestLength = 12 + request.length() + 1;
ByteBuffer buffer = ByteBuffer.allocate(requestLength);
buffer.order(ByteOrder.BIG_ENDIAN);
buffer.putInt(requestLength);
buffer.put(charsetEncoder.encode(CharBuffer.wrap(carrier)));
buffer.put(charsetEncoder.encode(CharBuffer.wrap(request)));
buffer.put(END_OF_MESSAGE_BYTE);
buffer.flip();
socketChannel.write(buffer);
return readResponse();
}
//Read Response
protected String readResponse() throws Exception {
CharsetDecoder charsetDecoder = Charset.forName("ISO-8859-1").newDecoder();
int responseHeaderLength = 12;
ByteBuffer responseHeaderBuf = ByteBuffer.allocate(responseHeaderLength);
responseHeaderBuf.order(ByteOrder.BIG_ENDIAN);
int bytesRead = 0;
do {
bytesRead = socketChannel.read(responseHeaderBuf);
} while (bytesRead!=-1 && responseHeaderBuf.position()<responseHeaderLength);
if (bytesRead==-1) {
throw new IOException(carrier + " : Remote connection closed unexpectedly");
}
responseHeaderBuf.flip();
int lengthField = responseHeaderBuf.getInt();
int responseLength = lengthField - responseHeaderLength;
responseHeaderBuf.clear();
ByteBuffer responseBuf = ByteBuffer.allocate(responseLength);
bytesRead = socketChannel.read(responseBuf);
if (bytesRead>responseBuf.limit() || bytesRead ==-1) {
throw new IOException(carrier + " : Remote connection closed unexpectedly");
}
responseBuf.flip();
if (responseBuf.get(responseBuf.limit()-1)==END_OF_MESSAGE_BYTE) {
responseBuf.limit(responseBuf.limit()-1);
}
responseBuf.clear();
String response = charsetDecoder.decode(responseBuf).toString();
return response;
}
public static void main(String[] args) throws Exception{
SimpleConnector simpleConnector = new SimpleConnector("carrier",new InetSocketAddress("localhost",9999));
String response=simpleConnector.sendRequest("Request");
System.out.println(response);
}
}
I'm trying to rewrite the following piece using Netty. By using following tutorial as reference.
http://tutorials.jenkov.com/netty/netty-tcp-client.html
https://www.baeldung.com/netty
https://github.com/deepanprabhu/netty-twoway-tcp-client-server
The problem I'm facing is I was able to connect to server but couldn't read or write from it . I'm using a ChannelInboundHandlerAdapter to do the read and write operations.
Here is my Netty Client
public class NettyClient {
int port;
Channel channel;
EventLoopGroup workGroup = new NioEventLoopGroup();
public NettyClient(int port){
this.port = port;
}
public ChannelFuture connectLoop() throws Exception {
try{
Bootstrap b = new Bootstrap();
b.group(workGroup);
b.channel(NioSocketChannel.class);
b.option(ChannelOption.SO_KEEPALIVE, true);
b.handler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new NettyClientHandler());
}
});
ChannelFuture channelFuture = b.connect("remote-ip", this.port).sync();
this.channel = channelFuture.channel();
return channelFuture;
}finally{
}
}
public void shutdown(){
workGroup.shutdownGracefully();
}
public static void main(String[] args) throws Exception{
try {
NettyClient nettyClient = new NettyClient(12000);
ChannelFuture channelFuture = nettyClient.connectLoop();
System.out.println("Sleep 2sec");
Thread.sleep(2000);
String command ="username";
final Charset charset = Charset.forName("ISO-8859-1");
int length = 13 + command.length();
if (channelFuture.isSuccess()) {
ByteBuf byteBuf = Unpooled.buffer(1024);
byteBuf.writeInt(length);
byteBuf.writeCharSequence("Some Info",charset);
byteBuf.writeCharSequence(command,charset);
channelFuture.channel().writeAndFlush(byteBuf).addListener(new ListenerImpl());
}
}
catch(Exception e){
System.out.println(e.getMessage());
System.out.println("Try Starting Server First !!");
}
finally {
}
}
private static final class ListenerImpl implements ChannelFutureListener{
public void operationComplete(ChannelFuture channelFuture) throws Exception {
if (channelFuture.isSuccess()){
System.out.println("Success"); //I can see success in Listener after write, but couldn't read response
}else {
System.out.println("Failed");
}
}
}
}
Handler
public class NettyClientHandler extends ChannelInboundHandlerAdapter {
#Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
super.channelReadComplete(ctx);
}
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("NettyClientHandler : channelRead" );
ByteBuf byteBuf = (ByteBuf) msg;
String message = byteBuf.toString(Charset.defaultCharset());
System.out.println("Received Message : " + message);
}
#Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
System.out.println("NettyClientHandler : channelActive" );
}
}
I Initially thought netty will work only with netty servers.But this answer clear my doubt about that
Does a Netty client work with a netty server only?
Can some one guide me, what I'm doing wrong ???
I think the problem is with your ClientHandler. you should writeAndFlush() in channelActive method invoked when a connection has been established between the tcp server and client. Please use the below updated code and see whether it fixes the problem.
#Sharable
public class NettyClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
#Override
public void channelRead0(ChannelHandlerContext ctx, ByteBuf byteBuf) throws Exception {
String message = byteBuf.toString(Charset.defaultCharset());
System.out.println("Received Message : " + message);
}
#Override
public void channelActive(ChannelHandlerContext channelHandlerContext){
channelHandlerContext.writeAndFlush(Unpooled.copiedBuffer("Netty Rocks!", CharsetUtil.UTF_8));
}
}

using netty to send several RTSP message

I want to create a RTSP client, to send some RTSP message. I use netty to write this, but my code can only send one message. how to send another message?
My client Code like this:
public class RtspClient {
public static class ClientHandler extends SimpleChannelInboundHandler<DefaultHttpResponse> {
#Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
protected void channelRead0(ChannelHandlerContext ctx, DefaultHttpResponse msg) throws Exception {
System.out.println(msg.toString());
}
}
public static void main(String[] args) throws InterruptedException {
EventLoopGroup workerGroup = new NioEventLoopGroup();
final ClientHandler handler = new ClientHandler();
Bootstrap b = new Bootstrap();
b.group(workerGroup);
b.channel(NioSocketChannel.class);
b.option(ChannelOption.SO_KEEPALIVE, true);
b.remoteAddress("127.0.0.1", 8557);
b.handler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel ch) {
ChannelPipeline p = ch.pipeline();
p.addLast("encoder", new RtspEncoder());
p.addLast("decoder", new RtspDecoder());
p.addLast(handler);
}
});
Channel channel = b.connect().sync().channel();
DefaultHttpRequest request = new DefaultHttpRequest(RtspVersions.RTSP_1_0, RtspMethods.PLAY, "rtsp:123");
request.headers().add(RtspHeaderNames.CSEQ, 1);
request.headers().add(RtspHeaderNames.SESSION, "294");
channel.writeAndFlush(request);
Thread.sleep(10000);
System.out.println(channel.isWritable());
System.out.println(channel.isActive());
request = new DefaultHttpRequest(RtspVersions.RTSP_1_0, RtspMethods.TEARDOWN, "rtsp3");
request.headers().add(RtspHeaderNames.CSEQ, 2);
request.headers().add(RtspHeaderNames.SESSION, "294");
}
channel.writeAndFlush(request);
Scanner sc = new Scanner(System.in);
sc.nextLine();
channel.closeFuture().sync();
}
this code could only send first message. The server did not receive the second data. how to send another message?
You want to use DefaultFullHttpRequest or you need to "terminate" each DefaultHttpRequest with a LastHttpContent.

Java Websocket Client without a Browser

I am working on a project that requires real-time interaction between users. I want to have a HTML5 web client (simple enough) and also a local client (preferably Java) with both being able to connect to the server. I have done some research and have not found a conclusive answer to whether or not the local client can connect to the server without a browser.
Question: Is there any way to connect from a local Java client to a websocket server without a browse? I have seen some browser wrappers in other languages that might make this possible. If not, I am open to suggestions.
Thanks.
You might also consider using JSR 356 - Java API for WebSocket. It is part of Java EE 7, but client can be run from plain Java SE without any issues. There are multiple implementations available right now and following will work in all of them:
programmatic API:
final WebSocketContainer webSocketContainer = ContainerProvider.getWebSocketContainer();
Session session = webSocketContainer.connectToServer(new Endpoint() {
#Override
public void onOpen(Session session, EndpointConfig config) {
// session.addMessageHandler( ... );
}
}, URI.create("ws://some.uri"));
annotated API:
public static void main(String[] args) throws IOException, DeploymentException {
final WebSocketContainer webSocketContainer = ContainerProvider.getWebSocketContainer();
webSocketContainer.connectToServer(MyEndpoint.class, URI.create("ws://some.uri"));
}
#ClientEndpoint
public static class MyEndpoint {
// text
#OnMessage
void onMessage(Session session, String message) {
// ...
}
// binary
#OnMessage
void onMessage(Session session, ByteBuffer message) {
// ...
}
// #OnClose, #OnOpen, #OnError
}
please see linked page for further details (full specification).
There are various implementations out here, basically every Java container has one. I am working on Glassfish/WebLogic implementation and its called Tyrus, feel free to try it out (we provide easy to use all in one bundle, see http://search.maven.org/...).
You most certainly CAN utilize WebSockets from desktop applications in Java, outside the browser sandbox. The thinking behind this is that you can create thick clients that create TCP connections, so of course they should be able to create WebSocket connections on top of those TCP connections.
One of the newest and best APIs for doing so is written by Kaazing, taking the point of view that a WebSocket is just like a socket and can be created using simple "ws://" URIs.
The API is discussed in detail on the Kaazing Gateway 5.0 Java WebSocket Documentation site. You can download the plain Gateway from Kaazing here
Create a websocket:
import com.kaazing.net.ws.WebSocket;
import com.kaazing.net.ws.WebSocketFactory;
wsFactory = WebSocketFactory.createWebSocketFactory();
ws = wsFactory.createWebSocket(URI.create("ws://example.com:8001/path"));
ws.connect(); // This will block or throw an exception if failed.
To send messages, add a WebSocketMessageWriter object:
WebSocketMessageWriter writer = ws.getMessageWriter();
String text = "Hello WebSocket!";
writer.writeText(text); // Send text message
To receive or consume messages, add WebSocket and WebSocketMessageReader objects:
wsFactory = WebSocketFactory.createWebSocketFactory();
ws = wsFactory.createWebSocket(URI.create("ws://example.com:8001/path"));
ws.connect(); // This will block or throw an exception if failed.
WebSocketMessageReader reader = ws.getMessageReader();
WebSocketMessageType type = null; // Block till a message arrives
// Loop till the connection goes away
while ((type = reader.next()) != WebSocketMessageType.EOS) {
switch (type) { // Handle both text and binary messages
case TEXT:
CharSequence text = reader.getText();
log("RECEIVED TEXT MESSAGE: " + text.toString());
break;
case BINARY:
ByteBuffer buffer = reader.getBinary();
log("RECEIVED BINARY MESSAGE: " + getHexDump(buffer));
break;
}
}
(Full Disclosure: I used to work at Kaazing Corporation as a server engineer.)
Vert.x has a java websocket client:
VertxFactory.newVertx()
.createHttpClient()
.setHost("localhost")
.setPort(8080)
.connectWebsocket("/ws", new Handler<WebSocket>() {
#Override
public void handle(final WebSocket webSocket) {
// Listen
webSocket.dataHandler(new Handler<Buffer>() {
#Override
public void handle(Buffer buff) {
log.info("Received {}", buff.toString());
}
});
// Publish
webSocket.writeTextFrame("Heya");
}
});
Netty is a good choice for such task, it's a high performance network application framework and it supports SSL elegantly, here is netty websocket client example from netty github:
public final class WebSocketClient {
static final String URL = System.getProperty("url", "ws://127.0.0.1:8080/websocket");
public static void main(String[] args) throws Exception {
URI uri = new URI(URL);
String scheme = uri.getScheme() == null? "ws" : uri.getScheme();
final String host = uri.getHost() == null? "127.0.0.1" : uri.getHost();
final int port;
if (uri.getPort() == -1) {
if ("ws".equalsIgnoreCase(scheme)) {
port = 80;
} else if ("wss".equalsIgnoreCase(scheme)) {
port = 443;
} else {
port = -1;
}
} else {
port = uri.getPort();
}
if (!"ws".equalsIgnoreCase(scheme) && !"wss".equalsIgnoreCase(scheme)) {
System.err.println("Only WS(S) is supported.");
return;
}
final boolean ssl = "wss".equalsIgnoreCase(scheme);
final SslContext sslCtx;
if (ssl) {
sslCtx = SslContextBuilder.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE).build();
} else {
sslCtx = null;
}
EventLoopGroup group = new NioEventLoopGroup();
try {
// Connect with V13 (RFC 6455 aka HyBi-17). You can change it to V08 or V00.
// If you change it to V00, ping is not supported and remember to change
// HttpResponseDecoder to WebSocketHttpResponseDecoder in the pipeline.
final WebSocketClientHandler handler =
new WebSocketClientHandler(
WebSocketClientHandshakerFactory.newHandshaker(
uri, WebSocketVersion.V13, null, true, new DefaultHttpHeaders()));
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
#Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline p = ch.pipeline();
if (sslCtx != null) {
p.addLast(sslCtx.newHandler(ch.alloc(), host, port));
}
p.addLast(
new HttpClientCodec(),
new HttpObjectAggregator(8192),
WebSocketClientCompressionHandler.INSTANCE,
handler);
}
});
Channel ch = b.connect(uri.getHost(), port).sync().channel();
handler.handshakeFuture().sync();
BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String msg = console.readLine();
if (msg == null) {
break;
} else if ("bye".equals(msg.toLowerCase())) {
ch.writeAndFlush(new CloseWebSocketFrame());
ch.closeFuture().sync();
break;
} else if ("ping".equals(msg.toLowerCase())) {
WebSocketFrame frame = new PingWebSocketFrame(Unpooled.wrappedBuffer(new byte[] { 8, 1, 8, 1 }));
ch.writeAndFlush(frame);
} else {
WebSocketFrame frame = new TextWebSocketFrame(msg);
ch.writeAndFlush(frame);
}
}
} finally {
group.shutdownGracefully();
}
}
}
public class WebSocketClientHandler extends SimpleChannelInboundHandler<Object> {
private final WebSocketClientHandshaker handshaker;
private ChannelPromise handshakeFuture;
public WebSocketClientHandler(WebSocketClientHandshaker handshaker) {
this.handshaker = handshaker;
}
public ChannelFuture handshakeFuture() {
return handshakeFuture;
}
#Override
public void handlerAdded(ChannelHandlerContext ctx) {
handshakeFuture = ctx.newPromise();
}
#Override
public void channelActive(ChannelHandlerContext ctx) {
handshaker.handshake(ctx.channel());
}
#Override
public void channelInactive(ChannelHandlerContext ctx) {
System.out.println("WebSocket Client disconnected!");
}
#Override
public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
Channel ch = ctx.channel();
if (!handshaker.isHandshakeComplete()) {
handshaker.finishHandshake(ch, (FullHttpResponse) msg);
System.out.println("WebSocket Client connected!");
handshakeFuture.setSuccess();
return;
}
if (msg instanceof FullHttpResponse) {
FullHttpResponse response = (FullHttpResponse) msg;
throw new IllegalStateException(
"Unexpected FullHttpResponse (getStatus=" + response.status() +
", content=" + response.content().toString(CharsetUtil.UTF_8) + ')');
}
WebSocketFrame frame = (WebSocketFrame) msg;
if (frame instanceof TextWebSocketFrame) {
TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;
System.out.println("WebSocket Client received message: " + textFrame.text());
} else if (frame instanceof PongWebSocketFrame) {
System.out.println("WebSocket Client received pong");
} else if (frame instanceof CloseWebSocketFrame) {
System.out.println("WebSocket Client received closing");
ch.close();
}
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
if (!handshakeFuture.isDone()) {
handshakeFuture.setFailure(cause);
}
ctx.close();
}
}

Categories