我还在学习RxJava。在另一个流中使用流的最佳方法是什么?还是反对反应式编程的原则?
我尝试编写的玩具示例包括TCP客户端和发送回大写输入的服务器。我想从标准输入中获取输入,将其发送到服务器并打印出客户端和服务器接收到的所有内容。
以下是该计划的预期输出:
(User input) apple
Server received: apple
Client received: APPLE
(User input) peach
Server received: peach
Client received: PEACH
我能够使用三个可观察量来实现这一点:
stdinStream
从标准输入中发出字符串serverStream
发出服务器接收的字符串clientStream
发出客户端收到的字符串。然后在inputStream
的创建中订阅clientStream
,如下所示:
private Observable<String> createClientStream(String host, int port, Observable<String> inputStream) {
return Observable.create(sub -> {
try (Socket socket = new Socket(host, port);
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
PrintWriter outWriter = new PrintWriter(outputStream, true);
) {
inputStream.subscribe(line -> {
outWriter.println(line);
try {
sub.onNext(inFromServer.readLine());
} catch (IOException e) {
sub.onError(e);
}
});
} catch (UnknownHostException e) {
sub.onError(e);
} catch (IOException e) {
sub.onError(e);
}
});
}
注意:我不想创建多个客户端,而是希望保持单个客户端运行,并指示它根据输入向服务器发送不同的值。因此,不希望将输入映射到新clientStream
的方法:
stdinStream.map(line -> createClientStream(line))
所以我的问题是:
clientStream
创建的一部分。我这样做是为了让我可以使用调度程序clientStream.scheduleOn(Schedulers.newThread)
轻松地异步运行它。也许我应该根据我的单客户要求做不同的事情?以下是完整的代码:https://gist.github.com/lintonye/25af58abdfcc688ad3c3
答案 0 :(得分:2)
您需要的是using
。将所有与套接字相关的对象放入Connection
类并给定输入序列,将其映射到一对println / readLine,同时保持单个连接。这是gist for a runnable example。
static class Connection {
Socket socket;
BufferedReader inFromServer;
DataOutputStream outputStream;
PrintWriter outWriter;
public Connection(String host, int port) {
try {
socket = new Socket(host, port);
inFromServer = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
outputStream = new DataOutputStream(socket.getOutputStream());
outWriter = new PrintWriter(outputStream, true);
} catch (IOException ex) {
Exceptions.propagate(ex);
}
}
public void close() {
try {
outWriter.close();
outputStream.close();
inFromServer.close();
socket.close();
} catch (IOException ex) {
Exceptions.propagate(ex);
}
}
}
public static void main(String[] args) {
runServer();
Observable<String> source = Observable.just("a", "b", "c");
String host = "localhost";
int port = 8080;
Observable.<String, Connection>using(() -> new Connection(host, port),
conn ->
source
.map(v -> {
conn.outWriter.println(v);
try {
return conn.inFromServer.readLine();
} catch (IOException ex) {
throw Exceptions.propagate(ex);
}
})
, Connection::close)
.subscribe(System.out::println);
}