Netty 是可写的()
Netty isWriteable()
我是 运行 在线游戏的 Netty 服务器,但是我遇到了一些奇怪的行为:
随机地,通道只是停止从服务器写入,即用户仍然连接并且接收到传入数据但传出数据未到达客户端。
我花时间对此进行了调试,我发现 channel.isWriteable() 在连接客户端时返回 false。
谁能阐明为什么会发生这种情况?
频道不再可写的原因是什么?
顺便说一句,这也发生在本地主机连接上。
public ChannelFuture write(Packet message) {
ioWrite++;
if (!channel.isConnected()) {
System.err.println("Trying to write to bad channel");
return null;
}
if (!channel.isWritable()) {
System.err.println("Channel buffer is full?");
}
if ((channel != null) && channel.isConnected()) {
return channel.write(message);
}
return null;
}
编码器:
public class GameProtocolEncoder extends OneToOneEncoder {
private ChannelBuffer response;
protected Object encode(ChannelHandlerContext channelHandlerContext, Channel channel, Object o) throws Exception {
Packet p = (Packet) o;
try {
byte[] data = p.getData();
int dataLength = p.getLength();
if (p.getLength() > 5000) {
System.err.println("unable to write data chunk to large");
return null;
}
if (!p.isBare()) {
int siz = 0;
siz += (p.getSize() == Packet.Size.VariableShort)
? 2
: 1;
siz += (p.getId() > 128)
? 2
: 1;
response = ChannelBuffers.buffer(siz + p.getLength());
int id = p.getId();
if (id< 128) {
response.writeByte(id);
} else {
response.writeByte((byte) ((id >> 8) + 128));
response.writeByte((byte) (id & 0xFF));
}
if (p.getSize() != Packet.Size.Fixed) { // variable length
if (p.getSize() == Packet.Size.VariableByte) {
if (dataLength > 255) { // trying to send more data then we can represent with 8 bits!
throw new IllegalArgumentException("Tried to send packet length " + dataLength
+ " in 8 bits [pid=" + p.getId() + "]");
}
response.writeByte((byte) dataLength);
} else if (p.getSize() == Packet.Size.VariableShort) {
if (dataLength > 5000) {
throw new IllegalArgumentException("Tried to send packet length to big: " + id);
}
response.writeShort((short) dataLength);
}
}
} else {
response = ChannelBuffers.buffer(dataLength);
}
response.writeBytes(p.getData());
return response;
} catch (Exception e) {
Logger.err("Error handling message: " + p);
Logger.err(e);
}
return null;
}
当通道的套接字发送缓冲区填满时,通道将停止写入,这反过来又会在发送方超过接收方时发生。
如果这种情况经常发生,您可能需要考虑加快接收代码的速度,但通常它随时可能发生,您所能做的就是推迟写入,直到通道再次可写入。
我认为问题出在您没有刷新频道。尝试用 channel.writeAndFlush(...).
替换 channel.write(...)
我是 运行 在线游戏的 Netty 服务器,但是我遇到了一些奇怪的行为:
随机地,通道只是停止从服务器写入,即用户仍然连接并且接收到传入数据但传出数据未到达客户端。
我花时间对此进行了调试,我发现 channel.isWriteable() 在连接客户端时返回 false。
谁能阐明为什么会发生这种情况?
频道不再可写的原因是什么?
顺便说一句,这也发生在本地主机连接上。
public ChannelFuture write(Packet message) {
ioWrite++;
if (!channel.isConnected()) {
System.err.println("Trying to write to bad channel");
return null;
}
if (!channel.isWritable()) {
System.err.println("Channel buffer is full?");
}
if ((channel != null) && channel.isConnected()) {
return channel.write(message);
}
return null;
}
编码器:
public class GameProtocolEncoder extends OneToOneEncoder {
private ChannelBuffer response;
protected Object encode(ChannelHandlerContext channelHandlerContext, Channel channel, Object o) throws Exception {
Packet p = (Packet) o;
try {
byte[] data = p.getData();
int dataLength = p.getLength();
if (p.getLength() > 5000) {
System.err.println("unable to write data chunk to large");
return null;
}
if (!p.isBare()) {
int siz = 0;
siz += (p.getSize() == Packet.Size.VariableShort)
? 2
: 1;
siz += (p.getId() > 128)
? 2
: 1;
response = ChannelBuffers.buffer(siz + p.getLength());
int id = p.getId();
if (id< 128) {
response.writeByte(id);
} else {
response.writeByte((byte) ((id >> 8) + 128));
response.writeByte((byte) (id & 0xFF));
}
if (p.getSize() != Packet.Size.Fixed) { // variable length
if (p.getSize() == Packet.Size.VariableByte) {
if (dataLength > 255) { // trying to send more data then we can represent with 8 bits!
throw new IllegalArgumentException("Tried to send packet length " + dataLength
+ " in 8 bits [pid=" + p.getId() + "]");
}
response.writeByte((byte) dataLength);
} else if (p.getSize() == Packet.Size.VariableShort) {
if (dataLength > 5000) {
throw new IllegalArgumentException("Tried to send packet length to big: " + id);
}
response.writeShort((short) dataLength);
}
}
} else {
response = ChannelBuffers.buffer(dataLength);
}
response.writeBytes(p.getData());
return response;
} catch (Exception e) {
Logger.err("Error handling message: " + p);
Logger.err(e);
}
return null;
}
当通道的套接字发送缓冲区填满时,通道将停止写入,这反过来又会在发送方超过接收方时发生。
如果这种情况经常发生,您可能需要考虑加快接收代码的速度,但通常它随时可能发生,您所能做的就是推迟写入,直到通道再次可写入。
我认为问题出在您没有刷新频道。尝试用 channel.writeAndFlush(...).
替换 channel.write(...)