我有一个使用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
。
解码时也是如此,反之亦然。
我希望事情会变得清楚
答案 0 :(得分:0)
我不会创建Packet类。我只用BufferedOutputStream
手动发送数据,如果要发送整个对象,则使用ObjectOutputStream
。您还可以将发送的内容告知远程设备(在附加数据之前发送String或其他任何内容)。
例如
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;
}
}
答案 1 :(得分:0)
我发现一种简单的方法是将一个数据包附加到另一个数据包上,方法是在类中添加一个变量和一些方法,如下所示:
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()
返回附加的数据包。
在编码器中,您检查是否添加了数据包,如果是,则只需调用添加的数据包的编码方法即可。像这样:
if (packet.isLinked()) {
out.writeBoolean(true);
encode(ctx, packet.getAttached(), out);
} else {
out.writeBoolean(false);
}
与解码器和您的自定义ChannelInboundHandler
相同。