我有一个使用Netty
构建的简单客户机/服务器系统,并且我使用数据包发送数据。在我的例子中,Packet
有两个方法来写入和读取BytBuf
。例如,包含字符串的数据包从字符串中获取字节,并将其写入ByteBuf
,然后发送,或者从ByteBuf
读取字节并创建消息。下面是来自我的数据包接口的代码片段:
import io.netty.buffer.ByteBuf;
public abstract class Packet {
public abstract void read(ByteBuf byteBuf);
public abstract void write(ByteBuf byteBuf);
}
首先,当接收到数据包时,我想检查是否有附加的数据包,然后我想访问或读取它。
问题在于数据包在接收时的实例化。我可以将第二个包附加到另一个包中,并将其存储在第一个包的本地变量中,但是当我使用Class.newInstance()
在服务器端重新创建该包时,它就消失了。
此外,据我所知,Netty的ByteBuf不能读取或编写自己的类。
我唯一的想法是发送多个包,我能避免这种情况吗?
编辑
我使用的数据包系统的定义。
由于没有很好地解释数据包系统,我将简要说明它的作用:
在我的例子中,有一个包包装了ByteBuf
。在Netty
中,发送数据的唯一方法是以字节的形式将其写入ByteBuf
。基于字符串的数据包的示例如下:
package com.sxf.protocol.chat.util.packets;
import io.netty.buffer.ByteBuf;
public class MessagePacket extends Packet {
private String msg;
public MessagePacket() {}
public MessagePacket(String message) {
this.msg = message;
}
@Override
public void read(ByteBuf byteBuf) {
byte[] msgBytes = new byte[byteBuf.readInt()];
byteBuf.readBytes(msgBytes);
msg = new String(msgBytes);
}
@Override
public void write(ByteBuf byteBuf) {
byte[] msgBytes = msg.getBytes();
byteBuf.writeInt(msgBytes.length);
byteBuf.writeBytes(msgBytes);
}
public String getMsg() {
return msg;
}
}
在创建Packet
时,您必须以String
的形式添加消息。在编码过程中,我调用write()
并传递通过管道发送的ByteBuf
。然后将消息格式化为字节并写入ByteBuf
。
同样的情况也会发生在解码过程中,反之亦然。
我希望事情变得清晰起来。
发布于 2019-05-25 21:20:00
我不会创建数据包类。我只会使用BufferedOutputStream
手动发送数据,或者如果您想发送整个对象,则使用ObjectOutputStream
。您还可以通知遥控器您发送的内容(在附加数据之前发送字符串或任何其他内容)。
例如:
package com.stackoverflow.q56304773;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
public class PacketSender {
private OutputStream networkStream;
public void sendObject(Object o,String objInfo) throws IOException {
try(BufferedOutputStream out=new BufferedOutputStream(getNetworkStream());
ObjectOutputStream objectSender=new ObjectOutputStream(out);
PrintWriter infoWriter=new PrintWriter(out)){
infoWriter.printf("Object:%s", objInfo);
objectSender.writeObject(o);
}
}
public OutputStream getNetworkStream() {
return networkStream;
}
public void setNetworkStream(OutputStream networkStream) {
this.networkStream = networkStream;
}
}
package com.stackoverflow.q56304773;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
public class PacketResciever {
private InputStream networkStream;
public void resv() throws IOException, ClassNotFoundException {
try(BufferedInputStream in=new BufferedInputStream(getNetworkStream());
BufferedReader infoReader=new BufferedReader(new InputStreamReader(in))){
String header=infoReader.readLine();
String[] splitted=header.split(":");
switch(splitted[0]) {
case "Object":
handleObject(new ObjectInputStream(in).readObject(),splitted[1]);
break;
//other cases
}
}
}
private void handleObject(Object readObject,String info) {
//search for handler and execute it
}
public InputStream getNetworkStream() {
return networkStream;
}
public void setNetworkStream(InputStream networkStream) {
this.networkStream = networkStream;
}
}
发布于 2019-05-31 06:23:30
我发现一种简单的方法是通过向类添加一个变量和几个方法来将一个包附加到另一个包中,如下所示:
package com.sxf.protocol.chat.util.packets;
import io.netty.buffer.ByteBuf;
public abstract class Packet {
private Packet attached;
public abstract void read(ByteBuf byteBuf);
public abstract void write(ByteBuf byteBuf);
public final boolean isLinked() {
return attached != null;
}
public final void append(Packet packet) {
attached = packet;
}
public final Packet getAttached() {
if (isLinked()) {
return attached;
}
throw new NullPointerException("unsafe access to getAttached");
}
}
使用append()
,您可以添加数据包并存储传递的数据包。isLinked()
返回数据包是否已附加。getAttached()
返回追加的数据包。
在编码器中,您可以检查是否添加了数据包,如果是,只需使用添加的数据包调用encode-method。如下所示:
if (packet.isLinked()) {
out.writeBoolean(true);
encode(ctx, packet.getAttached(), out);
} else {
out.writeBoolean(false);
}
解码器和您的自定义ChannelInboundHandler
也是如此。
https://stackoverflow.com/questions/56304773
复制相似问题