/** * Handle received selection keys. * * @param selectionKeys the selection keys. * @throws IOException */ private void handleSelectionKeys(Set<SelectionKey> selectionKeys) throws IOException { if (CollectionUtils.isEmpty(selectionKeys)) { // nothing happened return; } int size = selectionKeys.size(); this.logger.info("Handling [{}] selection keys", size); // something happened Iterator<SelectionKey> iterator = selectionKeys.iterator(); while (iterator.hasNext()) { SelectionKey selectionKey = iterator.next(); iterator.remove(); this.logger.debug("Remaining [{}] selection keys", selectionKeys.size()); // remove as to not process again. try { if (!selectionKey.isValid()) { continue; } SelectionKeyCommand selectionKeyCommand = this.selectionKeyCommandFactory.getSelectionKeyCommand(selectionKey); selectionKeyCommand.execute(selectionKey); } catch (Exception ex) { StringBuffer buffer = new StringBuffer("Error ["); buffer.append(ex.getMessage()); buffer.append("] on ["); buffer.append(selectionKey.channel()); buffer.append("] channel"); this.logger.error(buffer.toString(), ex); SocketChannel socketChannel = (SocketChannel) selectionKey.channel(); socketChannel.close(); } } this.logger.info("Handled [{}] selection keys", size); }
/* * (non-Javadoc) * * @see java.lang.Runnable#run() */ @Override public void run() { while (!stop) { try { selector.select(1000); Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> it = selectedKeys.iterator(); SelectionKey key = null; while (it.hasNext()) { key = it.next(); it.remove(); try { handleInput(key); } catch (Exception e) { if (key != null) { key.cancel(); if (key.channel() != null) key.channel().close(); } } } } catch (Throwable t) { t.printStackTrace(); } } // 多路复用器关闭后,所有注册在上面的Channel和Pipe等资源都会被自动去注册并关闭,所以不需要重复释放资源 if (selector != null) try { selector.close(); } catch (IOException e) { e.printStackTrace(); } }
private void listen() throws IOException { while (true) { int selec = selector.select(500); if (selec == 0) { continue; } Iterator<SelectionKey> iterator = this.selector.selectedKeys().iterator(); while (iterator.hasNext()) { SelectionKey selectionKey = iterator.next(); try { iterator.remove(); if (selectionKey.isAcceptable()) { ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel(); SocketChannel sc = ssc.accept(); sc.configureBlocking(false); sc.register(selector, SelectionKey.OP_READ); } else if (selectionKey.isReadable()) { read(selectionKey); } else if (selectionKey.isWritable()) { write(selectionKey); } } catch (Exception e) { // iterator.remove(); Don't use it! It can throw a exception! SocketChannel sc = (SocketChannel) selectionKey.channel(); sc.close(); } } } }
public void serve(int port) throws IOException { ServerSocketChannel serverChannel = ServerSocketChannel.open(); serverChannel.configureBlocking(false); ServerSocket ss = serverChannel.socket(); InetSocketAddress address = new InetSocketAddress(port); // Binds the server to the selected port ss.bind(address); // Opens the Selector for handling channels Selector selector = Selector.open(); // Registers the ServerSocket with the Selector to accept connections serverChannel.register(selector, SelectionKey.OP_ACCEPT); final ByteBuffer msg = ByteBuffer.wrap("Hi!\r\n".getBytes()); while (true) { try { // Waits for new events to process; blocks until the next incoming event selector.select(); } catch (IOException e) { e.printStackTrace(); break; } // Obtains all SelectionKey instances that received events Set<SelectionKey> readyKeys = selector.selectedKeys(); Iterator<SelectionKey> iterator = readyKeys.iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); iterator.remove(); try { // Checks if the event is a new connection ready to be accepted if (key.isAcceptable()) { ServerSocketChannel server = (ServerSocketChannel) key.channel(); SocketChannel client = server.accept(); client.configureBlocking(false); // Accepts client and registers it with the selector client.register( selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ, msg.duplicate()); System.out.println("Accepted connection from " + client); } // Checks if the socket is ready for writing data if (key.isWritable()) { SocketChannel client = (SocketChannel) key.channel(); ByteBuffer buffer = (ByteBuffer) key.attachment(); while (buffer.hasRemaining()) { // Writes data to the connected client if (client.write(buffer) == 0) { break; } } // Closes the connection client.close(); } } catch (IOException e) { key.cancel(); try { key.channel().close(); } catch (IOException e1) { } } } } }
private void write(SelectionKey key) { SocketChannel socketChannel = (SocketChannel) key.channel(); DataServerMessage sendMessage = mSendingData.get(socketChannel); boolean closeChannel = false; try { sendMessage.send(socketChannel); } catch (IOException e) { closeChannel = true; LOG.error(e.getMessage()); } if (sendMessage.finishSending() || closeChannel) { try { key.channel().close(); } catch (IOException e) { LOG.error(e.getMessage()); } key.cancel(); mReceivingData.remove(socketChannel); mSendingData.remove(socketChannel); sendMessage.close(); mBlocksLocker.unlock(Math.abs(sendMessage.getBlockId()), sendMessage.getLockId()); } }
private void read(SelectionKey key) throws IOException { SocketChannel socketChannel = (SocketChannel) key.channel(); // Clear out our read buffer so it's ready for new data readBuffer.clear(); // Attempt to read off the channel int numRead; try { numRead = socketChannel.read(readBuffer); } catch (IOException e) { key.cancel(); socketChannel.close(); System.out.println("Forceful shutdown"); return; } if (numRead == -1) { System.out.println("Graceful shutdown"); key.channel().close(); key.cancel(); return; } socketChannel.register(selector, SelectionKey.OP_WRITE); numMessages++; if (numMessages % 100000 == 0) { long elapsed = System.currentTimeMillis() - loopTime; loopTime = System.currentTimeMillis(); System.out.println(elapsed); } }
public void actionHandler(SelectionKey key) throws IOException { if (key.isAcceptable()) { ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel(); SocketChannel socketChannel = serverChannel.accept(); socketChannel.configureBlocking(false); socketChannel.register(roller, SelectionKey.OP_READ); } else if (key.isReadable()) { ByteBuffer buffer = ByteBuffer.allocate(16); SocketChannel socketChannel = (SocketChannel) key.channel(); socketChannel.read(buffer); buffer.flip(); String temp = decode(buffer); StringBuffer strBuffer = stringLocal.get(); if (strBuffer == null) { strBuffer = new StringBuffer(); } strBuffer.append(temp); if (temp.equals("\r\n")) { System.out.println(strBuffer.toString()); strBuffer = null; } stringLocal.set(strBuffer); } }
private void processKey(SelectionKey key) { try { if (key.isReadable()) { final DatagramChannel socketChannel = (DatagramChannel) key.channel(); reader.readAll(socketChannel); } if (key.isWritable()) { final DatagramChannel socketChannel = (DatagramChannel) key.channel(); try { int bytesJustWritten = writer.writeAll(socketChannel); contemplateThrottleWrites(bytesJustWritten); } catch (NotYetConnectedException e) { if (LOG.isDebugEnabled()) LOG.debug("", e); serverConnector.connectLater(); } catch (IOException e) { if (LOG.isDebugEnabled()) LOG.debug("", e); serverConnector.connectLater(); } } } catch (Exception e) { LOG.error("", e); if (!isClosed) closeEarlyAndQuietly(key.channel()); } }
private void handle(SelectionKey key) throws IOException { // TODO Auto-generated method stub ServerSocketChannel server = null; SocketChannel client = null; String receiveText = null; int count = 0; if (key.isAcceptable()) { // client require accept events server = (ServerSocketChannel) key.channel(); client = server.accept(); client.configureBlocking(false); client.register(selector, SelectionKey.OP_READ); } else if (key.isReadable()) { // 如果是read事件,则直接读取 client = (SocketChannel) key.channel(); recBuffer.clear(); count = client.read(recBuffer); if (count > 0) { recBuffer.flip(); receiveText = decode.decode(recBuffer.asReadOnlyBuffer()).toString(); System.out.println(client.toString() + ":" + receiveText); sendBuffer.clear(); sendBuffer.put((sdf.format(new Date()) + "服务器收到你的消息").getBytes()); sendBuffer.flip(); client.write(sendBuffer); dispatch(client, receiveText); client = (SocketChannel) key.channel(); client.register(selector, SelectionKey.OP_READ); } } }
void unregisterChannels(SelectionKeyRegistrationReference registrationReference) throws Exception { registrationReference.cancelRegistration(); SelectorIntraband defaultIntraband = (SelectorIntraband) registrationReference.getIntraband(); Selector selector = defaultIntraband.selector; Set<SelectionKey> keys = selector.keys(); while (!keys.isEmpty()) { selector.wakeup(); } SelectionKey readSelectionKey = registrationReference.readSelectionKey; SelectionKey writeSelectionKey = registrationReference.writeSelectionKey; SelectableChannel readSelectableChannel = readSelectionKey.channel(); SelectableChannel writeSelectableChannel = writeSelectionKey.channel(); while (readSelectableChannel.keyFor(selector) != null) ; while (writeSelectableChannel.keyFor(selector) != null) ; writeSelectableChannel.close(); readSelectableChannel.close(); }
private void read(SelectionKey key) throws IOException { SocketChannel socketChannel = (SocketChannel) key.channel(); // Clear out our read buffer so it's ready for new data this.readBuffer.clear(); // Attempt to read off the channel int numRead; try { numRead = socketChannel.read(this.readBuffer); } catch (IOException e) { // The remote forcibly closed the connection, cancel // the selection key and close the channel. key.cancel(); socketChannel.close(); return; } if (numRead == -1) { // Remote entity shut the socket down cleanly. Do the // same from our end and cancel the channel. key.channel().close(); key.cancel(); return; } // Hand the data off to our worker thread this.worker.processData(this, socketChannel, this.readBuffer.array(), numRead); }
public void stop() { try { lock.lock(); if (networkJob != null && !networkJob.isCancelled()) { networkJob.cancel(true); networkJob = null; } try { if (selector != null) { selector.wakeup(); boolean isContinue = true; while (isContinue) { try { for (SelectionKey selectionKey : selector.keys()) { selectionKey.channel().close(); selectionKey.cancel(); } isContinue = false; // continue till all keys are cancelled } catch (ConcurrentModificationException e) { logger.warn( "An exception occurred while closing a selector key : '{}'", e.getMessage()); } } selector.close(); } } catch (IOException e) { logger.warn("An exception occurred while closing the selector : '{}'", e.getMessage()); } if (broadcastKey != null) { try { broadcastKey.channel().close(); } catch (IOException e) { logger.warn( "An exception occurred while closing the broadcast channel : '{}'", e.getMessage()); } } if (unicastKey != null) { try { unicastKey.channel().close(); } catch (IOException e) { logger.warn( "An exception occurred while closing the unicast channel : '{}'", e.getMessage()); } } ipAddress = null; } finally { lock.unlock(); } }
@Override protected void processKey(SelectionKey key) throws IOException { if (key.isAcceptable()) { if (key.channel() == commandServerChannel) { acceptCommand(key); } else { if (commandChannel == null) { throw new IOException("Unexpected"); } accept(key); } } else { if (commandChannel == null) { throw new IOException("Unexpected"); } if (key.isReadable() && pendingChannels.containsKey(key.channel())) { ByteChannel channel = (ByteChannel) key.channel(); try { ByteBuffer readBuffer = pendingChannels.get(channel); int read = channel.read(readBuffer); if (read == -1) { throw new IOException("Pending channel closed"); } if (readBuffer.position() >= 5) { readBuffer.flip(); try { byte cmd = readBuffer.get(); if (cmd == CMD_OPEN_CHANNEL_ACK) { int tunnelId = readBuffer.getInt(); try { registerLeftChannel(tunnelId, channel); pendingChannels.remove(channel); } catch (IOException e) { logger.log(Level.INFO, "Spooling error: " + e.getMessage(), e); closeTunnel(tunnelId); } } else { throw new IOException("Unknown command"); } } finally { readBuffer.compact(); } } } catch (IOException e) { logger.log(Level.SEVERE, "PROTOCOL ERROR: " + e.getMessage(), e); close(channel); } } else { super.processKey(key); } } }
/** Handle a read event from a socket specified by the key. */ private void read(SelectionKey key) throws IOException { SocketChannel socketChannel = (SocketChannel) key.channel(); SocketAddress remoteAdr = socketChannel.socket().getRemoteSocketAddress(); // Clear out our read buffer so it's ready for new data readBuffer.clear(); // Attempt to read off the channel int numRead; try { numRead = socketChannel.read(readBuffer); } catch (IOException e) { // The remote forcibly closed the connection, cancel // the selection key and close the channel. key.cancel(); socketChannel.close(); clients.remove(remoteAdr); pendingWriteData.remove(socketChannel); logger.fine( "Connection forcibly closed(" + remoteAdr + ")! Remaining connections: " + clients.size()); throw new IOException("Remote forcibly closed the connection"); } if (numRead == -1) { // Remote entity shut the socket down cleanly. Do the // same from our end and cancel the channel. key.channel().close(); key.cancel(); clients.remove(remoteAdr); pendingWriteData.remove(socketChannel); logger.fine("Connection Closed(" + remoteAdr + ")! Remaining connections: " + clients.size()); throw new IOException("Remote closed the connection"); } // Make a correctly sized copy of the data before handing it to the client // byte[] rspByteData = new byte[numRead]; // System.arraycopy(readBuffer.array(), 0, rspByteData, 0, numRead); try { Object rspData = Converter.toObject(readBuffer.array()); // Hand the data off to our worker thread if (worker != null) { logger.finer("Handling incoming message..."); worker.processData(this, socketChannel.getRemoteAddress(), rspData); } else { logger.fine("No worker set, message unhandled!"); } } catch (Exception e) { e.printStackTrace(); } }
private SelectionKey checkIfSpinnedKey(final SelectionKey key) { if (!key.isValid() && key.channel().isOpen() && spinnedSelectorsHistory.containsKey(key.selector())) { final SelectionKey newKey = key.channel().keyFor(selector); newKey.attach(key.attachment()); return newKey; } return key; }
private void dispatch() throws IOException { SelectionKey key = null; for (SocketChannelOPSChangeRequest request : opsChangeRequstMap.values()) { key = request.getChannel().keyFor(selector); if (key != null) { // 写优先 if ((request.getOps() & SelectionKey.OP_WRITE) == SelectionKey.OP_WRITE) { key.interestOps(SelectionKey.OP_WRITE); request.clearOps(SelectionKey.OP_WRITE); } else if ((request.getOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) { key.interestOps(SelectionKey.OP_READ); request.clearOps(SelectionKey.OP_READ); } } } isWeakuped.set(false); if (selector.select(WaveriderConfig.WAVERIDER_DEFAULT_NETWORK_TIME_OUT) <= 0) { return; } Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) { key = (SelectionKey) iterator.next(); iterator.remove(); try { if (!key.isValid()) { continue; } else if (key.isAcceptable()) { onAccept(key); } else if (key.isReadable()) { // readerExecutor.execute(new NetworkTask(key, NETWORK_OPERATION_READ)); onRead(key); } else if (key.isWritable()) { // writerExecutor.execute(new NetworkTask(key, NETWORK_OPERATION_WRITE)); onWrite(key); } } catch (IOException e) { // 客户端连接出问题 Session session = (Session) key.attachment(); if (session != null) { session.onException(); // 释放Session sessionManager.freeSession(session); } opsChangeRequstMap.remove((SocketChannel) key.channel()); key.cancel(); key.channel().close(); e.printStackTrace(); logger.error("OOPS:Exception:", e); } } }
public void serve(int port) throws IOException { ServerSocketChannel serverChannel = ServerSocketChannel.open(); serverChannel.configureBlocking(false); ServerSocket ss = serverChannel.socket(); InetSocketAddress address = new InetSocketAddress(port); ss.bind(address); // 2 Selector selector = Selector.open(); // 2 serverChannel.register(selector, SelectionKey.OP_ACCEPT); // 3 final ByteBuffer msg = ByteBuffer.wrap("Hi!\r\n".getBytes()); for (; ; ) { try { selector.select(); // 4 } catch (IOException ex) { ex.printStackTrace(); // handle exception break; } Set<SelectionKey> readyKeys = selector.selectedKeys(); // 5 Iterator<SelectionKey> iterator = readyKeys.iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); iterator.remove(); try { if (key.isAcceptable()) { // 6 ServerSocketChannel server = (ServerSocketChannel) key.channel(); SocketChannel client = server.accept(); client.configureBlocking(false); client.register( selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ, msg.duplicate()); // 7 System.out.println("Accepted connection from " + client); } if (key.isWritable()) { // 8 SocketChannel client = (SocketChannel) key.channel(); ByteBuffer buffer = (ByteBuffer) key.attachment(); while (buffer.hasRemaining()) { if (client.write(buffer) == 0) { // 9 break; } } client.close(); // 10 } } catch (IOException ex) { key.cancel(); try { key.channel().close(); } catch (IOException cex) { // ignore on close } } } } }
private void read(SelectionKey key) throws IOException { SocketChannel socketChannel = (SocketChannel) key.channel(); DataServerMessage tMessage; if (mReceivingData.containsKey(socketChannel)) { tMessage = mReceivingData.get(socketChannel); } else { tMessage = DataServerMessage.createBlockRequestMessage(); mReceivingData.put(socketChannel, tMessage); } // Attempt to read off the channel int numRead; try { numRead = tMessage.recv(socketChannel); } catch (IOException e) { // The remote forcibly closed the connection, cancel the selection key and close the channel. key.cancel(); socketChannel.close(); mReceivingData.remove(socketChannel); mSendingData.remove(socketChannel); return; } if (numRead == -1) { // Remote entity shut the socket down cleanly. Do the same from our end and cancel the // channel. key.channel().close(); key.cancel(); mReceivingData.remove(socketChannel); mSendingData.remove(socketChannel); return; } if (tMessage.isMessageReady()) { if (tMessage.getBlockId() <= 0) { LOG.error("Invalid block id " + tMessage.getBlockId()); return; } key.interestOps(SelectionKey.OP_WRITE); LOG.info("Get request for " + tMessage.getBlockId()); int lockId = mBlocksLocker.lock(tMessage.getBlockId()); DataServerMessage tResponseMessage = DataServerMessage.createBlockResponseMessage( true, tMessage.getBlockId(), tMessage.getOffset(), tMessage.getLength()); tResponseMessage.setLockId(lockId); mSendingData.put(socketChannel, tResponseMessage); } }
/** {@inheritDoc} */ public SelectableChannel acceptWithoutRegistration(SelectionKey key) throws IOException { boolean isAccepted; int retryNum = 0; do { try { isAccepted = true; return ((ServerSocketChannel) key.channel()).accept(); } catch (IOException ex) { if (!key.isValid()) throw ex; isAccepted = false; try { // Let's try to recover here from too many open file Thread.sleep(1000); } catch (InterruptedException ex1) { throw new IOException(ex1.getMessage()); } logger.log( Level.WARNING, LogMessages.WARNING_GRIZZLY_TCPSELECTOR_HANDLER_ACCEPTCHANNEL_EXCEPTION(), ex); } } while (!isAccepted && retryNum++ < maxAcceptRetries); throw new IOException("Accept retries exceeded"); }
public void run() { try { while (!flag) { System.out.println("waiting connected......."); selector.select(); Iterator<SelectionKey> keys = selector.selectedKeys().iterator(); while (keys.hasNext()) { SelectionKey key = keys.next(); keys.remove(); if (key.isAcceptable()) { ServerSocketChannel ssc = (ServerSocketChannel) key.channel(); SocketChannel sc = ssc.accept(); sc.configureBlocking(false); SelectionKey clientKey = sc.register(selector, SelectionKey.OP_READ); System.out.println(sc.socket().getInetAddress().getHostAddress() + " 已连接"); } if (key.isReadable()) { read(key); } } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
/** * Called when a new connection is pending on the underlying {@link ServerSocketChannel}. * * @param key The {@link SelectionKey} for the socket on which a connection is pending. * @throws IOException if an error occurs while accepting the new connection. */ protected void accept(SelectionKey key) throws IOException { // Pull out the socket channel that has a connection pending ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel(); // Accept the connection SocketChannel socketChannel = serverSocketChannel.accept(); Socket socket = socketChannel.socket(); // Check if our AcceptPolicy will allow this new connection if (this.acceptPolicy != null && !this.acceptPolicy.shouldRetain(socketChannel, this.getSocketSelector().keys().size())) { if (log.logTrace()) { log.trace("Closing accepted connection (accept policy enforced)"); } socketChannel.close(); return; } this.registerChannel(socketChannel); // Register the new socket. This will promote it to an SSLSocket // if we're configured for HTTPS. this.registerSocket(socket, this.host, this.port, false); // Add the new SocketChannel to our Selector socketChannel.configureBlocking(false); SelectionKey acceptKey = socketChannel.register(this.getSocketSelector(), SelectionKey.OP_READ); this.resetClientTimer(socketChannel.socket()); }
@Override public void run() { try { while (true) { this.selector.select(SELECT_MILLISECONDS); if (Thread.interrupted()) break; Iterator<SelectionKey> i = this.selector.selectedKeys().iterator(); while (i.hasNext()) { SelectionKey key = i.next(); SelectableChannel channel = key.channel(); handleReadableChannel(key, channel); handleWritableChannel(key, channel); i.remove(); } } } catch (ClosedByInterruptException e) { // User-requested interrupt, so clean up } catch (IOException e) { reportIOException(e); } for (Map.Entry<SelectableChannel, SelectableChannel> e : this.outputs.entrySet()) { closeChannelAndReportException(e.getKey()); closeChannelAndReportException(e.getValue()); } for (SelectableChannel c : this.outputBuffers.keySet()) closeChannelAndReportException(c); }
private void handleInput(SelectionKey key) throws IOException { if (key != null && key.isValid()) { SocketChannel sc = (SocketChannel) key.channel(); if (key.isConnectable()) { if (sc.finishConnect()) { sc.register(selector, SelectionKey.OP_READ); doWrite(sc); } else System.exit(1); } if (key.isReadable()) { ByteBuffer readBuffer = ByteBuffer.allocate(1024); int readBytes = sc.read(readBuffer); if (readBytes > 0) { readBuffer.flip(); byte[] bytes = new byte[readBuffer.remaining()]; readBuffer.get(bytes); String body = new String(bytes, "UTF-8"); System.out.println("Now is : " + body); this.stop = true; } else if (readBytes < 0) { key.cancel(); sc.close(); } else { } } } }
@Override public Void call() throws Exception { ServerSocketChannel clientConnection = (ServerSocketChannel) selectionKey.channel(); SocketChannel channel = clientConnection.accept(); if (channel != null) { channel.configureBlocking(false); LOGGER.info( String.format("%s accepted client connection from %s", name, channel.getRemoteAddress())); try { final HttpRequest.HttpRequestWrapper requestWrapper = requestParser.parse(read(channel)); MethodHandler handler = RequestHandlerFactory.newInstance(requestWrapper.getRequestLine().getMethod()); HttpResponse.HttpResponseWrapper responseWrapper = handler.handle(requestWrapper); write(channel, responseWrapper); } finally { channel.close(); } LOGGER.info(String.format("%s is done.", name)); } return null; }
/** * Start the server running - accepting connections, receiving messages. If the server is already * running, it will not be started again. This method is designed to be called in its own thread * and will not return until the server is stopped. * * @throws RuntimeException if the server fails */ public void run() { // ensure that the server is not started twice if (!state.compareAndSet(State.STOPPED, State.RUNNING)) { started(true); return; } Selector selector = null; ServerSocketChannel server = null; try { selector = Selector.open(); server = ServerSocketChannel.open(); server.socket().bind(new InetSocketAddress(port)); server.configureBlocking(false); server.register(selector, SelectionKey.OP_ACCEPT); started(false); while (state.get() == State.RUNNING) { selector.select(100); // check every 100ms whether the server has been requested to stop for (Iterator<SelectionKey> it = selector.selectedKeys().iterator(); it.hasNext(); ) { SelectionKey key = it.next(); try { // remove key from the ready list it.remove(); if (key.isConnectable()) { ((SocketChannel) key.channel()).finishConnect(); } if (key.isAcceptable()) { // accept connection SocketChannel client = server.accept(); client.configureBlocking(false); client.socket().setTcpNoDelay(true); // channel is registered for further events such as read or write SelectionKey acceptKey = client.register(selector, SelectionKey.OP_READ); connection(acceptKey); } if (key.isReadable()) { for (ByteBuffer message : readIncomingMessage(key)) { messageReceived(message, key); } } } catch (IOException ioe) { resetKey(key); disconnected(key); } } } } catch (Throwable e) { throw new RuntimeException("Server failure: " + e.getMessage()); } finally { try { selector.close(); server.socket().close(); server.close(); state.set(State.STOPPED); stopped(); } catch (Exception e) { // do nothing - server failed } } }
/** * Read as many messages as available on the client connection. * * @param key the client connection to read. * @return the messages read. * @throws IOException if the client connection is closed. */ private List<ByteBuffer> readIncomingMessage(SelectionKey key) throws IOException { ByteBuffer readBuffer = readBuffers.get(key); if (readBuffer == null) { readBuffer = ByteBuffer.allocate(defaultBufferSize); readBuffers.put(key, readBuffer); } // read data pending in the channel // 1), maybe only receive partial message even if message is not big // 2), maybe multiple messages exist, will try to read all them // 3), maybe a message is too big to be fully put into buffer, then this // read will repeat multiple times if (((ReadableByteChannel) key.channel()).read(readBuffer) == -1) { throw new IOException("Read on closed key"); } readBuffer.flip(); List<ByteBuffer> result = new ArrayList<ByteBuffer>(); // process data received in the buffer // 1), if only partial message is received, keep using readBuffer for coming request // 2), if multiple messages in the buffer, so need while loop here // 3), if message is too big, re-allocate the readBuffer and keep reading // 4), one readMessage(..) handle at most one full message ByteBuffer msg = readMessage(key, readBuffer); while (msg != null) { result.add(msg); msg = readMessage(key, readBuffer); } return result; }
/** * Send the given message to the given client. The message does not need to have the length of the * message prepended. It is not guaranteed the message will arrive, as it can't be determined if * writing on a closed connection (it could appear to work). This won't be known until later when * get a disconnected callback is made. * * @param channelKey the key of the client to which the message should be sent. * @param buffer the message to send. */ public void write(SelectionKey channelKey, byte[] buffer) { short len = (short) buffer.length; byte[] lengthBytes = messageLength.lengthToBytes(len); // copying into byte buffer is actually faster than writing to channel twice over many (>10000) // runs ByteBuffer writeBuffer = ByteBuffer.allocate(len + lengthBytes.length); writeBuffer.put(lengthBytes); writeBuffer.put(buffer); writeBuffer.flip(); if (buffer != null && state.get() == State.RUNNING) { int bytesWritten; try { // only 1 thread can write to a channel at a time SocketChannel channel = (SocketChannel) channelKey.channel(); synchronized (channel) { bytesWritten = channel.write(writeBuffer); } if (bytesWritten == -1) { resetKey(channelKey); disconnected(channelKey); } } catch (Exception e) { resetKey(channelKey); disconnected(channelKey); } } }
private void dispose(Selector localSelector, LinkedBlockingQueue localSelectorTasks) { Assert.eval(Thread.currentThread() == this); if (localSelector != null) { for (Object element : localSelector.keys()) { try { SelectionKey key = (SelectionKey) element; cleanupChannel(key.channel(), null); } catch (Exception e) { logger.warn("Exception trying to close channel", e); } } try { localSelector.close(); } catch (Exception e) { if ((Os.isMac()) && (Os.isUnix()) && (e.getMessage().equals("Bad file descriptor"))) { // I can't find a specific bug about this, but I also can't seem to prevent the // exception on the Mac. // So just logging this as warning. logger.warn("Exception trying to close selector: " + e.getMessage()); } else { logger.error("Exception trying to close selector", e); } } } }
public void handleAccept(SelectionKey key) throws IOException { ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel(); SocketChannel socketChannel = serverSocketChannel.accept(); log.info("Server: accept client socket " + socketChannel); socketChannel.configureBlocking(false); socketChannel.register(key.selector(), SelectionKey.OP_READ); }
private void doConnect(SelectionKey key) { SocketChannel sc = (SocketChannel) key.channel(); TCConnectionImpl conn = (TCConnectionImpl) key.attachment(); try { if (sc.finishConnect()) { sc.register(selector, SelectionKey.OP_READ, conn); conn.finishConnect(); } else { String errMsg = "finishConnect() returned false, but no exception thrown"; if (logger.isInfoEnabled()) { logger.info(errMsg); } conn.fireErrorEvent(new Exception(errMsg), null); } } catch (IOException ioe) { if (logger.isInfoEnabled()) { logger.info("IOException attempting to finish socket connection", ioe); } conn.fireErrorEvent(ioe, null); } }