Exception java.nio.channels.ClosedChannelException when write to client channel
Asked Answered
D

3

15

I have created a game server using netty 3.5.8. At first, there is not any problem with sending data from server to client. But when server operates for a while, there are many exceptions [java.nio.channels.ClosedChannelException] when I write data to the client channel.

Anyone has gotten this exception before. Is there any tip to fix this? I think about cache buffer cause this.

My code sample like this:

ChannelBuffer bff = ChannelBuffers.buffer(18);
bff.writeByte(Events.S_SERVER_PUSH);  
bff.writeByte((byte)0);
bff.writeInt(idRoom);            
bff.writeInt(playerCnt);
bff.writeInt(gameCnt);
bff.writeInt(freePlayer);
channel.write(bff);

Exception: java.nio.channels.ClosedChannelException

java.nio.channels.ClosedChannelException
        at org.jboss.netty.channel.socket.nio.AbstractNioWorker.cleanUpWriteBuffer(AbstractNioWorker.java:784)
        at org.jboss.netty.channel.socket.nio.AbstractNioWorker.writeFromUserCode(AbstractNioWorker.java:507)
        at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.handleAcceptedSocket(NioServerSocketPipelineSink.java:129)
        at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.eventSunk(NioServerSocketPipelineSink.java:66)
        at org.jboss.netty.channel.Channels.write(Channels.java:733)
        at org.jboss.netty.handler.codec.oneone.OneToOneEncoder.doEncode(OneToOneEncoder.java:71)
        at org.jboss.netty.handler.codec.oneone.OneToOneEncoder.handleDownstream(OneToOneEncoder.java:60)
        at org.jboss.netty.channel.Channels.write(Channels.java:712)
        at org.jboss.netty.channel.Channels.write(Channels.java:679)
        at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:248)
       at myclass.SendPushData(GameRoom.java:231)
        at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:296)
        at org.jboss.netty.handler.codec.frame.FrameDecoder.unfoldAndFireMessageReceived(FrameDecoder.java:458)
        at org.jboss.netty.handler.codec.frame.FrameDecoder.callDecode(FrameDecoder.java:439)
        at org.jboss.netty.handler.codec.frame.FrameDecoder.messageReceived(FrameDecoder.java:303)
        at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268)
        at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255)
        at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:84)
        at org.jboss.netty.channel.socket.nio.AbstractNioWorker.processSelectedKeys(AbstractNioWorker.java:471)
        at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:332)
        at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:35)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)
Davisdavison answered 25/12, 2012 at 9:28 Comment(3)
The exception raises more frequently when i write to send data to multi-client in for-loopDavisdavison
Thanks Tube. Code like this for (PlayerInfo p:this.players.values()){ ChannelBuffer bff = ChannelBuffers.buffer(18); bff.writeByte(Events.S_SERVER_PUSH); bff.writeByte(typePush);bff.writeInt(idRoom); bff.writeInt(idGame); bff.writeInt(gameCnt*2); bff.writeInt(freePlayer); p.getChannel().write(bff); Thread.sleep(100); } }Davisdavison
Related question - #24975955Eddi
T
12

ClosedChannelException merely tells you that the connection has been closed, so, the write request you issued could not be done. It usually means either:

(1) your application closed the connection somewhere else before you write the message or
(2) your peer closed the connection before reading your message.

If you fix (1) and (2), you should not see the ClosedChannelException anymore.

Tiffa answered 26/12, 2012 at 4:27 Comment(4)
It only means (1). A peer close results in an IOException: 'connection reset'.Rundell
No. You can check the code of netty. channel.write() or ctx.write() will call AbstractUnsafe's write() method, which may set ClosedChannelException to the promise if the outbound buffer is null. And the buffer may be cleared if the peer has closed the connection.Villosity
@AdrianLiu Then Netty has misused the exception. Its Javadoc is perfectly clear.Rundell
It seems as though none of the more accessible (by Google search) answers have much in the way of authority, just unsupported claims. For instance, an empty buffer is not a null buffer. If a remote peer can cause the outboundBuffer to become null, then something is very wrong with version 4, maybe 3 and 5 as well. A remote peer shouldn’t be able to close the server channel, it’s absurd. At the same time, the closure on the server side is somehow elusive when one tries to locate it. This error is poorly understood.Henriques
R
4

ClosedChannelException means you have closed the channel and continued to use it. It is a programming error on your part.

Rundell answered 26/1, 2014 at 2:58 Comment(2)
EJP - How can one find out for sure which exception is thrown when a connection is interrupted. I made an attempt at answering this here - #24975955 I'd appreciate it if you could answer the question and give me some feedback on my answer. Thank you.Eddi
@Eddi Rather difficult as you've deleted it, but there were at least two errors. ClosedChannelException and AsynchronousCloseException have nothing to do with the peer.Rundell
Z
1

I recently ran into this problem, and it was a bit of a pain to debug. In my case, the reason was that I was creating network connection from GUI thread. Basically I just had a simple button and established websocket connection there. This seemed innocent enough to me, as this was just supposed to be a quick test to figure out connection capabilities of my app. What I didn't know is that Android 3.0+ explicitly forbids any networking from GUI thread, so it throws an internal exception and then the connection gets closed. Unfortunately, none of that was communicated to me by the library I used (Jetty), and because this is an async process - you just gotta know where to look.

TLDR: If you run into this, make sure to check you are not creating connections from GUI thread, because Android WILL close them. :D

Zeb answered 10/8, 2023 at 7:44 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.