3

I'm an RxJava newbie trying to accomplish the following simple task:

  • connect via a socket to a server that regularly sends data
  • read the data as it arrives
  • write a heartbeat message to the server every n milliseconds if the socket is writeable

I wrote working RxJava programs to "connect and read" and "connect and write", but now I want to write a program that does both. I have a function to connect to a socket:

Observable<SocketChannel> connect(String host,int port) { ...

...a function to read from it

Observable<byte[]> readFromSocket(SocketChannel s) {

...and a function to test for writeability (it returns the socket when it's writeable)

Observable<SocketChannel> whenWritable(SocketChannel s) {

So my approach looks like the following:

connect("localhost", 31337).forEach(socket -> {
    readFromSocket(socket)
        .forEach(bytes -> printf("read %d bytes",bytes.length);
    Observable
        .interval(2500, TimeUnit.MILLISECONDS)
        .flatMap(ignore -> whenWritable(socket))
        .forEach(ignore -> println("write heart beat"));
    });

When I run the program, the "read n bytes" messages appear regularly, but the heart beats are not written.

The following program works, however:

connect("localhost", 31337)
    .flatMap(s -> 
        Observable
            .interval(2500, TimeUnit.MILLISECONDS)
            .flatMap(ignore -> whenWritable(s)))
    .forEach(ignore -> println("write heart beat"));

What's the problem here, and is my method of doing read and write customary in RxJava?

1 Answers1

1

It's probably because readFromSocket(socket) is synchronous, then readFromSocket(socket).forEach will block and the codes after it won't be able to run. You can add a log after readFromSocket(socket).forEach to check it.

To resolve this issue, you can use readFromSocket(socket).subscribeOn(Schedulers.io()) to run the read actions in the IO thread pools.

zsxwing
  • 20,270
  • 4
  • 37
  • 59