Sergеу Isupov
Sergеу Isupov

Reputation: 504

Netty. Write to channel outside a handler

is there a way to write to channel outside an event handler. I want to write to the channel a string I type in the console. Is that possible?

fun main() {
    //Bootstrapping
    val eventLoopGroup = NioEventLoopGroup()
    val serverBootstrap = ServerBootstrap()
    serverBootstrap.group(eventLoopGroup)
    serverBootstrap.channel(NioServerSocketChannel::class.java)
    serverBootstrap.localAddress(InetSocketAddress(9988))
    serverBootstrap.childHandler(object : ChannelInitializer<SocketChannel>() {
        override fun initChannel(channel: SocketChannel?) {
            channel?.pipeline()
                ?.addLast(StringEncoder(StandardCharsets.UTF_8))
                ?.addLast(StringDecoder(StandardCharsets.UTF_8))
                ?.addLast(RemoteKeyboardHandler())
        }
    })

    val ch = serverBootstrap.bind().sync().channel()
    while (true) {
        val input = readLine()
        val future = ch.writeAndFlush(input)
        future.addListener {
            println(it.isSuccess)
            println(it.cause())
        }
    }
}

This is my server code. In a handler, I just send a "Hello world" string on connection. I get OperationNotSupportedException. I found on SO that I can't write to server channel. Maybe that's the point. So what should I do in this case?

Upvotes: 1

Views: 1350

Answers (2)

Norman Maurer
Norman Maurer

Reputation: 23557

writing to a ServerChannel is not supported as this socket just accepts new sockets. You want to write to the child Channel which you have a reference to in your ChannelInitializer.

Upvotes: 0

Max pm
Max pm

Reputation: 83

First if all it would be helpful if you post your client/server class here.

You can get the channel object from the bootstrap:

Channel channel = new Bootstrap()
                    .group(workerGroup)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline()
                                    .addLast(new StringEncoder())
                                    .addLast(new StringDecoder())
                                    .addLast(new YourChannelHandler();
                        }
                    }).connect(YourIp, YourPort).sync().channel();

The .channel() returns a the channel where you can use writeAndFlush and pass a String

channel.writeAndFlush("Example Message");

When you want to add a console input, you can do that directly below:

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.Epoll;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollSocketChannel;
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;
import io.netty.handler.codec.string.StringEncoder;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

public class Client {

    private static final boolean EPOLL = Epoll.isAvailable();
    private static final int PORT = 25112;
    private static final String HOST = "localhost";

    private Channel ch;

    private static Integer count;


    // instead you can use a method to start the client
    public Client() {
        EventLoopGroup workerGroup = (EPOLL) ? new EpollEventLoopGroup() : new NioEventLoopGroup();

        try {
            ch = new Bootstrap()
                    .group(workerGroup)
                    .channel((EPOLL) ? EpollSocketChannel.class : NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ch.pipeline()
                                    .addLast(new StringEncoder(StandardCharsets.UTF_8))
                                    .addLast(new StringDecoder(StandardCharsets.UTF_8))
                                    .addLast(new ClientMessageHandler());
                        }
                    }).connect(HOST, PORT).sync().channel();


            // console input
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            String line = "";

            while ((line = reader.readLine()) != null) {
                if (line.startsWith("!exit") || line.startsWith("!disconnect")) {
                    reader.close();
                    line = null;
                    ch.disconnect();
                    break;
                } else if (line.toCharArray().length == 0) {
                    continue;
                } else if (line.startsWith("!ping")) {
                    ch.writeAndFlush(String.valueOf(System.nanoTime()));
                    continue;
                }

                ch.writeAndFlush(line);
            }

            //runCommandPromptReading();
        } catch (InterruptedException | IOException e) {
            e.printStackTrace();
        } finally {
            workerGroup.shutdownGracefully();
        }
    }

//    private void runCommandPromptReading() throws IOException {
//        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
//        String line = "";
//
//        while ((line = reader.readLine()) != null) {
//            if (line.startsWith("!exit") || line.startsWith("!disconnect")) {
//                reader.close();
//                line = null;
//                ch.disconnect();
//                break;
//            } else if (line.toCharArray().length == 0) {
//                continue;
//            } else if (line.startsWith("!ping")) {
//                ch.writeAndFlush(String.valueOf(System.nanoTime()));
//                continue;
//            }
//
//            ch.writeAndFlush(line);
//        }
}

I hope this is what you wanted

Upvotes: 2

Related Questions