sockets - Java NIO with InputStream.available() -
good day.
i'm using nio multiplexing , don't want allocate additional buffers in app till sure have enough bytes in socket read entire application packet. each application packet contains 4 bytes of packet length (header) , following bytes of packet body. want read 4 bytes of packet length if available , following bytes of packet body if available. so, code can that:
private final bytebuffer read_buffer = bytebuffer.wrap(new byte[read_buffer_size]); ... iterator<selectionkey> selectedkeys = selector.selectedkeys().iterator(); while (selectedkeys.hasnext()) { selectionkey key = selectedkeys.next(); selectedkeys.remove(); connection con = (connection) key.attachment(); switch (key.readyops()) { case selectionkey.op_accept: acceptconnection(key); break; case selectionkey.op_read: readpacket(key, con); //** } } ... private final void readpacket(final selectionkey key, final connection con) { read_buffer.clear(); int result = -2; try { result = con.read(read_buffer); } catch (ioexception e) {} //* packet processing goes here }
in * can obtain:
- less 4 bytes read header;
- 4 bytes header not enough bytes packet body
- enough bytes read n packets (header + body), part of (n+1) packet
in either of 3 cases have store readed data in additional bytebuffer, read_buffer used next connection in **.
what want do:
public class connection { private final bytechannel bytechannel; private final inputstream in; private int lastpacketsize = -1; connection(final socket socket) { bytechannel = socket.getchannel(); in = socket.getinputstream(); } int read(final bytebuffer buf) throws ioexception { return bytechannel.read(buf); } int available() { return in.available(); } void setlastpacketsize(int size) { lastpacketsize = size; } int getlastpacketsize() { return lastpacketsize; } } private final intbuffer header_buffer = intbuffer.wrap(new int[1]); private final void readpacket(final selectionkey key, final connection con) { int packetsize = con.getlastpacketsize(); if (packetsize < 0) { if (con.available() < 4) return; int result = -2; header_buffer.clear(); try { result = con.read(header_buffer); } catch (ioexception e) {} if (result != 4) { closeconnection(key); return; } packetsize = header_buffer.get(); con.setlastpacketsize(packetsize); } if (con.available() < packetsize) return; result = -2; read_buffer.clear(); read_buffer.limit(packetsize); try { result = con.read(read_buffer); } catch (ioexception e) {} if (result != packetsize) { closeconnection(key); return; } con.setlastpacketsize(-1); //packet processing goes here }
i have found under hood socket's inputstream uses ioctl(fd, fionread, pbytes) on linux. can rely on con.available() in scenario or can fail? if can fail reasons , how improve code overcome these reasons?
if you're using non-blocking mode can't use inputstream
@ all. can't have ever run code.
there's not point in you're trying do. read every time op_read fires until have enough data process.
Comments
Post a Comment