Java 如何使Vertx反应式RecordParser无长度地发出消息?
我有一个反应式Vertex TCPserver,它使用RecordParser处理具有2字节长度头的消息。RecordParser的工作是理解长度部分和消息部分 问题1Java 如何使Vertx反应式RecordParser无长度地发出消息?,java,rx-java2,vert.x,Java,Rx Java2,Vert.x,我有一个反应式Vertex TCPserver,它使用RecordParser处理具有2字节长度头的消息。RecordParser的工作是理解长度部分和消息部分 问题1 recordparser正确解释recordparser内的数据和系统输出。但当我添加以下行时,系统输出不再打印。这可能与它在不同的线程上执行有关?我不确定 frameParser.toFlowable() .subscribe(onNext->System.out.println(onNext)); 问题2 添加问题1中的行
recordparser正确解释recordparser内的数据和系统输出。但当我添加以下行时,系统输出不再打印。这可能与它在不同的线程上执行有关?我不确定
frameParser.toFlowable()
.subscribe(onNext->System.out.println(onNext));
问题2添加问题1中的行后,onNext将以块的形式打印其接收到的所有数据。我想我理解,它在接收时转发数据。
输出 5bd34970-da5a-44e1-b167-0d32d2e70bb2
成功
? [它是不可打印的字节4]
12
三十四 我的最终目标是只获取没有长度标题的消息。任何指示都将不胜感激
代码
//客户端字节[]b={0,4,0x31,0x32,0x33,0x34}发送的数据;
导入io.reactivex.Flowable;
导入io.reactivex.Single;
导入io.vertx.core.net.NetServerOptions;
导入io.vertx.reactivex.RxHelper;
导入io.vertx.reactivex.core.AbstractVerticle;
导入io.vertx.reactivex.core.vertx;
导入io.vertx.reactivex.core.buffer.buffer;
导入io.vertx.reactivex.core.net.NetServer;
导入io.vertx.reactivex.core.net.NetSocket;
导入io.vertx.reactivex.core.parsetools.RecordParser;
公共类TCPRxServer扩展了AbstractVerticle{
单插座;
私有FrameToken expectedToken=FrameToken.SIZE;
RecordParser解析器,frameParser=null;
静态流动性;
静态单观测量;
@凌驾
public void start()引发异常{
NetServerOptions=newnetserveroptions();
opt.setIdleTimeout(500);//现在可以帮助调试
可观察=vertx.createNetServer(opt)
.connectHandler(套接字->{
frameParser=get2byteFrameParser();
//frameParser.toFlowable()
//.subscribe(onNext->System.out.println(onNext));
处理程序(frameParser);
})
.rxListen(8888);
observable.subscribe(onSuccess->System.out.println(“onSuccess”),onError->onError.printStackTrace();
}
受保护的RecordParser get2byteFrameParser(){
返回RecordParser.newFixed(2,缓冲区->{
开关(预期停止){
箱子尺寸:
字节[]b=buffer.getString(0,2)
.getBytes();
int frameSize=((b[0])&0xFF){
//部署
系统输出打印项次(id);
//
},呃->{
//无法部署
err.printStackTrace();
});
}
}
p.s.我已经根据的SO响应定制了LengthPrefixedStream,在行为上没有差异
observable=vertx.createNetServer(opt)
.connectHandler(套接字->{
新长度PrefixedStream(套接字).toFlowable()
.subscribe(onNext->System.out.println(onNext));
})
.rxListen(8888);
我无法运行您粘贴的代码。如果您的目标是只获取没有长度头的消息,那么以下情况如何:(我没有使用RecordParser)
import io.reactivex.Flowable;
导入io.reactivex.Single;
导入io.vertx.core.net.NetServerOptions;
导入io.vertx.reactivex.core.AbstractVerticle;
导入io.vertx.reactivex.core.vertx;
导入io.vertx.reactivex.core.buffer.buffer;
导入io.vertx.reactivex.core.net.NetClient;
导入io.vertx.reactivex.core.net.NetServer;
导入io.vertx.reactivex.core.net.NetSocket;
导入io.vertx.reactivex.core.parsetools.RecordParser;
公共类newtcrpxserver扩展了AbstractVerticle{
单插座;
RecordParser解析器,frameParser=null;
静态流动性;
静态单观测量;
@凌驾
public void start()引发异常{
NetServerOptions=newnetserveroptions();
opt.setIdleTimeout(500);//现在可以帮助调试
可观察=vertx.createNetServer(opt)
.connectHandler(套接字->{
处理程序(buffer->onNewframe(buffer));
})
.rxListen(8888);
observable.subscribe(onSuccess->System.out.println(“onSuccess”),onError->onError.printStackTrace();
}
私有void onNewframe(缓冲区){
int size=buffer.getInt(0);
buffercontent=Buffer.getBuffer(4,大小+4);
vertx.eventBus().rxSend(“MESSAGE”,content.toString()).subscribe();
}
公共静态void main(字符串[]args){
newtcrpxserver server=new newtcrpxserver();
Vertx vertxx=Vertx.Vertx();
单部署=io.vertx.reactivex.core.RxHelper.deployVerticle(vertxx,服务器);
部署。订阅(id->{
//部署
系统输出打印项次(id);
//
},呃->{
//无法部署
err.printStackTrace();
});
//测试客户机
io.vertx.reactivex.core.RxHelper.deployVerticle(vertxx,新TestTCPClient()).subscribe();
}
静态类TestTCPClient扩展了AbstractVerticle{
@凌驾
public void start()引发异常{
vertx.eventBus().consumer(“消息”,消息->{
对象体
import io.reactivex.Flowable;
import io.reactivex.Single;
import io.vertx.core.net.NetServerOptions;
import io.vertx.reactivex.core.AbstractVerticle;
import io.vertx.reactivex.core.Vertx;
import io.vertx.reactivex.core.buffer.Buffer;
import io.vertx.reactivex.core.net.NetClient;
import io.vertx.reactivex.core.net.NetServer;
import io.vertx.reactivex.core.net.NetSocket;
import io.vertx.reactivex.core.parsetools.RecordParser;
public class NewTCPRxServer extends AbstractVerticle {
Single<NetSocket> observableNetSocket;
RecordParser parser, frameParser = null;
static Flowable<Buffer> y;
static Single<NetServer> observable;
@Override
public void start() throws Exception {
NetServerOptions opt = new NetServerOptions();
opt.setIdleTimeout(500); // large to assist in debugging for now
observable = vertx.createNetServer(opt)
.connectHandler(socket -> {
socket.handler(buffer -> onNewframe(buffer));
})
.rxListen(8888);
observable.subscribe(onSuccess -> System.out.println("OnSuccess"), onError -> onError.printStackTrace());
}
private void onNewframe(Buffer buffer) {
int size = buffer.getInt(0);
Buffer content = buffer.getBuffer(4, size + 4);
vertx.eventBus().rxSend("MESSAGE", content.toString()).subscribe();
}
public static void main(String[] args) {
NewTCPRxServer server = new NewTCPRxServer();
Vertx vertxx = Vertx.vertx();
Single<String> deployment = io.vertx.reactivex.core.RxHelper.deployVerticle(vertxx, server);
deployment.subscribe(id -> {
// Deployed
System.out.println(id);
//
}, err -> {
// Could not deploy
err.printStackTrace();
});
// a test client
io.vertx.reactivex.core.RxHelper.deployVerticle(vertxx, new TestTCPClient()).subscribe();
}
static class TestTCPClient extends AbstractVerticle {
@Override
public void start() throws Exception {
vertx.eventBus().consumer("MESSAGE", message -> {
Object body = message.body();
// we receive 'hello world' here means the TCP server processed
// it successfully!
System.out.println("[Message] - " + body);
});
NetClient netclient = vertx.createNetClient();
netclient.connect(8888, "localhost", result -> {
if (result.failed()) {
System.err.println("Client unable to connect");
return;
}
NetSocket socket = result.result();
// sending "hello world" every second
vertx.periodicStream(1000).handler(tick -> {
String msg = "Hello world";
Buffer frame = Buffer.buffer(msg.length() + 4);
frame.appendInt(msg.length());
frame.appendString(msg);
socket.write(frame);
});
});
}
}
}
import io.vertx.core.Handler;
import io.vertx.reactivex.core.buffer.Buffer;
import io.vertx.reactivex.core.parsetools.RecordParser;
import io.vertx.reactivex.core.streams.ReadStream;
public class LengthPrefixedStream implements io.vertx.core.streams.ReadStream<Buffer> {
private final RecordParser recordParser;
private FrameToken expectedToken = FrameToken.SIZE;
public LengthPrefixedStream(ReadStream<Buffer> stream) {
recordParser = RecordParser.newFixed(2, stream);
}
@Override
public io.vertx.core.streams.ReadStream<Buffer> exceptionHandler(Handler<Throwable> handler) {
recordParser.exceptionHandler(handler);
return this;
}
@Override
public io.vertx.core.streams.ReadStream<Buffer> handler(Handler<Buffer> handler) {
if (handler == null) {
recordParser.handler(null);
return this;
}
recordParser.handler(buffer -> {
switch (expectedToken) {
case SIZE:
byte[] b = buffer.getString(0, 2)
.getBytes();
int frameSize = (((b[0]) & 0xFF) << 8) | ((b[1]) & 0xFF);
System.out.println("size: " + frameSize);
recordParser.fixedSizeMode(frameSize);
expectedToken = FrameToken.PAYLOAD;
break;
case PAYLOAD:
System.out.println("Payload: |" + buffer + "|");
recordParser.fixedSizeMode(2);
expectedToken = FrameToken.SIZE;
handler.handle(buffer);
break;
}
});
return this;
}
@Override
public io.vertx.core.streams.ReadStream<Buffer> pause() {
recordParser.pause();
return this;
}
@Override
public io.vertx.core.streams.ReadStream<Buffer> resume() {
recordParser.resume();
return this;
}
@Override
public io.vertx.core.streams.ReadStream<Buffer> endHandler(Handler<Void> endHandler) {
recordParser.endHandler(endHandler);
return this;
}
}
import io.reactivex.Single;
import io.reactivex.disposables.Disposable;
import io.vertx.core.VertxOptions;
import io.vertx.core.net.NetServerOptions;
import io.vertx.reactivex.FlowableHelper;
import io.vertx.reactivex.core.AbstractVerticle;
import io.vertx.reactivex.core.RxHelper;
import io.vertx.reactivex.core.Vertx;
import io.vertx.reactivex.core.net.NetServer;
import io.vertx.reactivex.core.parsetools.RecordParser;
public class TCPRxServer extends AbstractVerticle {
RecordParser frameParser = null;
private NetServer server;
private Disposable disposable;
@Override
public void start() throws Exception {
NetServerOptions opt = new NetServerOptions();
opt.setIdleTimeout(500); // large to assist in debugging for now
server = vertx.createNetServer(opt);// Create a TCP server
Single<NetServer> rxSingleServer = server.connectHandler(socket -> {
LengthPrefixedStream frameParser = new LengthPrefixedStream(socket);
FlowableHelper.toFlowable(frameParser)
.subscribe(onNext -> System.out.println(onNext));
})
.rxListen(8888, "localhost");
disposable = rxSingleServer.subscribe(s -> System.out.println("Server is listening"),
onError -> System.out.println(onError));
}
@Override
public void stop() throws Exception {
disposable.dispose();
server.close(completionHandler -> {
if (completionHandler.succeeded()) {
System.out.println("TCPRxServer stopped");
}
else {
System.out.println(completionHandler.cause());
}
});
}
public static void main(String[] args) {
VertxOptions ops = new VertxOptions();
// We are using clustered as we have verticles in different VMs and we
// want to make sure when something is placed on the eventbus, a
// verticle on a different VM receives it.
ops.setClustered(true);
Vertx.clusteredVertx(ops, result -> {
if (result.succeeded()) {
Single<String> deployment = RxHelper.deployVerticle(result.result(), new TCPRxServer());
deployment.subscribe(id -> {
System.out.println(id);
// Deployed
}, err -> {
err.printStackTrace();
});
}
});
}
}
byte[] serialized = SerializationUtils.serialize(o);
senderSocket.write(Buffer.buffer(serialized).appendString(MSG_DELIMITER));
System.out.println("I sent some bytes: " + serialized.length);
protected static String MSG_DELIMITER = "_I_Am_so0o_UNIQUEQE_";
protected Vertx vertx;
protected final RecordParser parser = RecordParser.newDelimited(MSG_DELIMITER, new Output());
public static main(String[] args) {
this.vertx = Vertx.vertx();
this.vertx.deployVerticle(new Receiver());
}
public class Receiver extends AbstractVerticle {
@Override
public void start() {
NetServer receiver = this.vertx.createNetServer();
receiver.connectHandler(socket ->
socket.handler(parser::handle));
receiver.listen(port, host, res -> {
if (res.succeeded()) {
System.out.println("Receiver is now listening!");
} else {
System.out.println("Failed to bind!");
}
});
}
@Override
public void stop() {
System.out.println("Receiver stopped");
}
}
public class Output implements Handler<Buffer> {
@Override
public void handle(Buffer event) {
try {
E deserialized = (E) SerializationUtils.deserialize(event.getBytes());
queue.put(deserialized);
System.out.println("I received some bytes: " + event.length());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}