private void handleReads(SelectionKey sk, MemcachedNode qa) throws IOException { Operation currentOp = qa.getCurrentReadOp(); ByteBuffer rbuf = qa.getRbuf(); final SocketChannel channel = qa.getChannel(); int read = channel.read(rbuf); while (read > 0) { getLogger().debug("Read %d bytes", read); rbuf.flip(); while (rbuf.remaining() > 0) { assert currentOp != null : "No read operation"; currentOp.readFromBuffer(rbuf); if (currentOp.getState() == OperationState.COMPLETE) { getLogger() .debug( "Completed read op: %s and giving the next %d bytes", currentOp, rbuf.remaining()); Operation op = qa.removeCurrentReadOp(); assert op == currentOp : "Expected to pop " + currentOp + " got " + op; currentOp = qa.getCurrentReadOp(); } } rbuf.clear(); read = channel.read(rbuf); } }
/** * Create a client socket for the specified InetSocketAddress. Creates an SSL socket if the type * specified is SSL or SSL_MUTUALAUTH. * * @param type * @param inetSocketAddress * @return the socket. */ public Socket createSocket(String type, InetSocketAddress inetSocketAddress) throws IOException { try { String host = inetSocketAddress.getHostName(); int port = inetSocketAddress.getPort(); if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, "createSocket(" + type + ", " + host + ", " + port + ")"); } if (type.equals(SSL) || type.equals(SSL_MUTUALAUTH)) { return createSSLSocket(host, port); } else { Socket socket = null; if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, "Creating CLEAR_TEXT socket for:" + port); } if (orb.getORBData().connectionSocketType().equals(ORBConstants.SOCKETCHANNEL)) { SocketChannel socketChannel = ORBUtility.openSocketChannel(inetSocketAddress); socket = socketChannel.socket(); } else { socket = new Socket(inetSocketAddress.getHostName(), inetSocketAddress.getPort()); } // Disable Nagle's algorithm (i.e. always send immediately). socket.setTcpNoDelay(true); return socket; } } catch (Exception ex) { if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, "Exception creating socket", ex); } throw new RuntimeException(ex); } }
/** * 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); } } }
/** * Reads incoming data from the client: * * <UL> * <LI>Reads some bytes from the SocketChannel * <LI>create a protocolTask, to process this data, possibly generating an answer * <LI>Inserts the Task to the ThreadPool * </UL> * * @throws * @throws IOException in case of an IOException during reading */ public void read() { // do not read if OLD.protocol has terminated. only write of pending data is // allowed if (_protocol.shouldClose()) { return; } SocketAddress address = _sChannel.socket().getRemoteSocketAddress(); logger.info("Reading from " + address); ByteBuffer buf = ByteBuffer.allocate(BUFFER_SIZE); int numBytesRead = 0; try { numBytesRead = _sChannel.read(buf); } catch (IOException e) { numBytesRead = -1; } // is the channel closed?? if (numBytesRead == -1) { // No more bytes can be read from the channel logger.info("client on " + address + " has disconnected"); closeConnection(); // tell the OLD.protocol that the connection terminated. _protocol.connectionTerminated(); return; } // add the buffer to the OLD.protocol task buf.flip(); _task.addBytes(buf); // add the OLD.protocol task to the OLD.reactor _data.getExecutor().execute(_task); }
protected SelectableChannel getSelectableChannel( SocketAddress remoteAddress, SocketAddress localAddress) throws IOException { SocketChannel newSocketChannel = SocketChannel.open(); Socket newSocket = newSocketChannel.socket(); if (receiveBufferSize > 0) { try { newSocket.setReceiveBufferSize(receiveBufferSize); } catch (SocketException se) { if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, "setReceiveBufferSize exception ", se); } catch (IllegalArgumentException iae) { if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, "setReceiveBufferSize exception ", iae); } } if (sendBufferSize > 0) { try { newSocket.setSendBufferSize(sendBufferSize); } catch (SocketException se) { if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, "setSendBufferSize exception ", se); } catch (IllegalArgumentException iae) { if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, "setSendBufferSize exception ", iae); } } newSocket.setReuseAddress(reuseAddress); if (localAddress != null) newSocket.bind(localAddress); newSocketChannel.configureBlocking(false); return newSocketChannel; }
public static void chooseDispatcher(SocketChannel channel, int op) { if (channel.isRegistered()) { for (Dispatcher dispatcher : dispatchers) { SelectionKey key = channel.keyFor(dispatcher.getSelector()); if (key != null && key.isValid() && (key.interestOps() == op)) { return; } } for (Dispatcher dispatcher : dispatchers) { SelectionKey key = channel.keyFor(dispatcher.getSelector()); if (key != null && key.isValid() && (key.interestOps() == 0)) { if (op == SelectionKey.OP_READ) { dispatcher.addChannelForRead(channel); } else if (op == SelectionKey.OP_WRITE) { dispatcher.addChannelForWrite(channel); } return; } } } else { if (op == SelectionKey.OP_READ) { nextDispatcher().addChannelForRead(channel); } else if (op == SelectionKey.OP_WRITE) { nextDispatcher().addChannelForWrite(channel); } } }
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 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(); } } } }
/** * Starts a new Thread and connects to server * * @throws IOException */ public Thread connect() throws IOException { this.running = true; this.readyState = WEBSOCKET_STATE_CONNECTING; // open socket socketChannel = SocketChannel.open(); socketChannel.configureBlocking(false); // set address socketChannel.connect(new InetSocketAddress(uri.getHost(), port)); // start a thread to make connection // More info: // http://groups.google.com/group/android-developers/browse_thread/thread/45a8b53e9bf60d82 // http://stackoverflow.com/questions/2879455/android-2-2-and-bad-address-family-on-socket-connect System.setProperty("java.net.preferIPv4Stack", "true"); System.setProperty("java.net.preferIPv6Addresses", "false"); selector = Selector.open(); socketChannel.register(selector, SelectionKey.OP_CONNECT); Log.v("websocket", "Starting a new thread to manage data reading/writing"); Thread th = new Thread(this); th.start(); // return thread object for explicit closing, if needed return th; }
@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; }
void send(byte[] data) throws IOException { SocketChannel channel = (SocketChannel) key.channel(); verboseLog("TCP write", data); byte[] lengthArray = new byte[2]; lengthArray[0] = (byte) (data.length >>> 8); lengthArray[1] = (byte) (data.length & 0xFF); ByteBuffer[] buffers = new ByteBuffer[2]; buffers[0] = ByteBuffer.wrap(lengthArray); buffers[1] = ByteBuffer.wrap(data); int nsent = 0; key.interestOps(SelectionKey.OP_WRITE); try { while (nsent < data.length + 2) { if (key.isWritable()) { long n = channel.write(buffers); if (n < 0) throw new EOFException(); nsent += (int) n; if (nsent < data.length + 2 && System.currentTimeMillis() > endTime) throw new SocketTimeoutException(); } else blockUntil(key, endTime); } } finally { if (key.isValid()) key.interestOps(0); } }
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); } }
/** * Creates a socket channel and connects it to a socket address. * * <p>This method performs a call to {@code open()} followed by a call to {@code * connect(SocketAddress)}. * * @param address the socket address to be connected to. * @return the new connected channel. * @throws AsynchronousCloseException if this channel is closed by another thread while this * method is executing. * @throws ClosedByInterruptException if another thread interrupts the calling thread while this * operation is executing. The calling thread will have the interrupt state set and the * channel will be closed. * @throws UnresolvedAddressException if the address is not resolved. * @throws UnsupportedAddressTypeException if the address type is not supported. * @throws IOException if an I/O error occurs. */ public static SocketChannel open(SocketAddress address) throws IOException { SocketChannel socketChannel = open(); if (socketChannel != null) { socketChannel.connect(address); } return socketChannel; }
public void writeResponsePacket(SocketChannel socketChannel, ResponsePacket responsePacket) { try { ByteBuffer byteBuffer; byteBuffer = ByteBuffer.allocate(BUFFER_SIZE); byte[] marshalObject = MarshalHelper.objectToBytes(responsePacket); byte[] marshalHeader = MarshalHelper.int32ToBytes(marshalObject.length); byteBuffer.clear(); byteBuffer.put(marshalHeader); byteBuffer.put(marshalObject); byteBuffer.flip(); // If no connection now, please ignore it (usually in async calling) try { if (socketChannel.isConnected()) { socketChannel.write(byteBuffer); } } catch (IOException e) { socketChannel.close(); } } catch (IOException e) { e.printStackTrace(); } }
/** * Test of a large write on a socket to understand what happens when the write is greater than the * combined size of the client send buffer and the server receive buffer and the server side of * the socket is either not accepted or already shutdown. * * @throws IOException * @throws InterruptedException */ public void testDirectSockets_largeWrite_NotAccepted() throws IOException, InterruptedException { final Random r = new Random(); // Get a socket addresss for an unused port. final InetSocketAddress serverAddr = new InetSocketAddress(getPort(0)); // First our ServerSocket final ServerSocket ss = new ServerSocket(); try { // Size of the server socket receive buffer. final int receiveBufferSize = ss.getReceiveBufferSize(); // Allocate buffer twice as large as the receive buffer. final byte[] largeBuffer = new byte[receiveBufferSize * 10]; if (log.isInfoEnabled()) { log.info( "receiveBufferSize=" + receiveBufferSize + ", largeBufferSize=" + largeBuffer.length); } // fill buffer with random data. r.nextBytes(largeBuffer); // bind the ServerSocket to the specified port. ss.bind(serverAddr); // Now the first Client SocketChannel final SocketChannel cs = SocketChannel.open(); try { /* * Note: true if connection made. false if connection in * progress. */ final boolean immediate = cs.connect(serverAddr); if (!immediate) { // Did not connect immediately, so finish connect now. if (!cs.finishConnect()) { fail("Did not connect."); } } /* * Attempt to write data. The server socket is not yet accepted. * This should hit a timeout. */ assertTimeout(10L, TimeUnit.SECONDS, new WriteBufferTask(cs, ByteBuffer.wrap(largeBuffer))); accept(ss); } finally { cs.close(); } } finally { ss.close(); } }
// actual connection logic private void _connect() throws IOException { // Continuous loop that is only supposed to end when "close" is called. selector.select(); Set<SelectionKey> keys = selector.selectedKeys(); Iterator<SelectionKey> i = keys.iterator(); while (i.hasNext()) { SelectionKey key = i.next(); i.remove(); if (key.isConnectable()) { if (socketChannel.isConnectionPending()) { socketChannel.finishConnect(); } socketChannel.register(selector, SelectionKey.OP_READ); _writeHandshake(); } if (key.isReadable()) { try { _read(); } catch (NoSuchAlgorithmException nsa) { this.onError(nsa); } } } }
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 boolean finishConnect() throws IOException { if (_socketType == SocketType.Incoming) { throw new IOException("Invalid State-Connect called on an Incoming (server) Socket"); } if (_channel == null) { throw new IOException("Invalid State - finishConnect called on closed channel"); } try { if (_channel.finishConnect()) { _channel.socket().setKeepAlive(true); // LOG.info(this + "Connected to: " + _address.getAddress().getHostAddress() + ":" + // _address.getPort() + " via Interface:" + // _channel.socket().getLocalAddress().getHostAddress()); return true; } } catch (IOException e) { // LOG.error("channel.finishConnect to address:" + _address.getAddress().getHostAddress() +" // port: " + _address.getPort() + " threw exception:" + e.toString()); throw e; } return false; }
/** Closes the underlying sockets and socket streams. */ @Override public void close() throws IOException { SocketChannel s = _s; _s = null; if (s != null) { s.close(); } /* OutputStream os = _os; _os = null; InputStream is = _is; _is = null; try { if (os != null) os.close(); if (is != null) is.close(); } finally { if (s != null) s.close(); } */ }
private static void setClientSocketOptions(SocketChannel channel) throws IOException { channel.socket().setPerformancePreferences(0, 1, 3); channel.socket().setTcpNoDelay(true); probeAndSetSize(false, 2 << 16, 2 << 10, channel); probeAndSetSize(true, 2 << 15, 2 << 10, channel); channel.configureBlocking(false); }
@JSFunction public static Object connect(Context cx, Scriptable thisObj, Object[] args, Function func) { final TCPImpl tcp = (TCPImpl) thisObj; String host = stringArg(args, 0); int port = intArg(args, 1); boolean success = false; SocketChannel newChannel = null; try { InetSocketAddress targetAddress = new InetSocketAddress(host, port); NetworkPolicy netPolicy = tcp.getNetworkPolicy(); if ((netPolicy != null) && !netPolicy.allowConnection(targetAddress)) { log.debug("Disallowed connection to {} due to network policy", targetAddress); setErrno(Constants.EINVAL); return null; } if (log.isDebugEnabled()) { log.debug("Client connecting to {}:{}", host, port); } clearErrno(); if (tcp.boundAddress == null) { newChannel = SocketChannel.open(); } else { newChannel = SocketChannel.open(tcp.boundAddress); } tcp.clientChannel = newChannel; getRunner().registerCloseable(newChannel); tcp.clientInit(); tcp.clientChannel.connect(targetAddress); tcp.selKey = tcp.clientChannel.register( getRunner().getSelector(), SelectionKey.OP_CONNECT, new SelectorHandler() { @Override public void selected(SelectionKey key) { tcp.clientSelected(key); } }); tcp.pendingConnect = (PendingOp) cx.newObject(thisObj, PendingOp.CLASS_NAME); success = true; return tcp.pendingConnect; } catch (IOException ioe) { log.debug("Error on connect: {}", ioe); setErrno(Constants.EIO); return null; } finally { if (!success && (newChannel != null)) { getRunner().unregisterCloseable(newChannel); try { newChannel.close(); } catch (IOException ioe) { log.debug("Error closing channel that might be closed: {}", ioe); } } } }
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); } }
/** Handle new OP_CONNECT ops. */ protected void onConnectOp(Context ctx, ConnectChannelOperation selectionKeyOp) throws IOException { SocketChannel socketChannel = (SocketChannel) selectionKeyOp.getChannel(); SocketAddress remoteAddress = selectionKeyOp.getRemoteAddress(); CallbackHandler callbackHandler = selectionKeyOp.getCallbackHandler(); CallbackHandlerSelectionKeyAttachment attachment = new CallbackHandlerSelectionKeyAttachment(callbackHandler); SelectionKey key = socketChannel.register(selector, 0, attachment); attachment.associateKey(key); boolean isConnected; try { isConnected = socketChannel.connect(remoteAddress); } catch (Exception e) { if (logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Exception occured when tried to connect socket", e); } // set isConnected to true to let callback handler to know about the problem happened isConnected = true; } // if channel was connected immediately or exception occured if (isConnected) { onConnectInterest(key, ctx); } else { key.interestOps(SelectionKey.OP_CONNECT); } }
private void reconnect() { FVLog.log(LogLevel.INFO, this, "trying to reconnect to ", this.hostname, ":", this.port); // reset our state to unconnected (might be a NOOP) this.isConnected = false; this.msgStream = null; // try to connect socket to controller try { if (this.sock != null) // note that this automatically unregisters from selector this.sock.close(); this.sock = SocketChannel.open(); sock.configureBlocking(false); // set to non-blocking InetSocketAddress addr = new InetSocketAddress(hostname, port); if (addr.isUnresolved()) { FVLog.log(LogLevel.INFO, this, "retrying: failed to resolve hostname: ", hostname); this.reconnectLater(); return; } this.isConnected = this.sock.connect(addr); // try to connect // register into event loop this.loop.register(this.sock, SelectionKey.OP_CONNECT, this); } catch (IOException e) { FVLog.log(LogLevel.CRIT, this, "Trying to reconnect; trying later; got : ", e); this.reconnectLater(); } }
/** * attempts to send data to the client<br> * if all the data has been successfully sent, the ConnectionHandler will automatically switch to * read only mode, otherwise it'll stay in it's current mode (which is read / write). * * @throws IOException if the write operation fails * @throws ClosedChannelException if the channel have been closed while registering to the * Selector */ public synchronized void write() { if (_outData.size() == 0) { // if nothing left in the output string, go back to read mode switchToReadOnlyMode(); return; } // if there is something to send ByteBuffer buf = _outData.remove(0); if (buf.remaining() != 0) { try { _sChannel.write(buf); } catch (IOException e) { // this should never happen. e.printStackTrace(); } // check if the buffer contains more data if (buf.remaining() != 0) { _outData.add(0, buf); } } // check if the OLD.protocol indicated close. if (_protocol.shouldClose()) { switchToWriteOnlyMode(); if (buf.remaining() == 0) { closeConnection(); SocketAddress address = _sChannel.socket().getRemoteSocketAddress(); logger.info("disconnecting client on " + address); } } }
/** Check for new client connections */ private void acceptNewConnections() { try { SocketChannel clientChannel; // since sSockChan is non-blocking, this will return immediately // regardless of whether there is a connection available while ((clientChannel = sSockChan.accept()) != null) { if (getContext().getServer().isRedirectActive()) { LOG.debug( "Client redirected to {}: {}", getContext().getServer().getRedirectAddress().getHostAddress(), clientChannel.socket().getInetAddress().getHostAddress()); redirectAndKill(clientChannel.socket()); continue; } Client client = getContext().getClients().addNewClient(clientChannel, readSelector, SEND_BUFFER_SIZE); if (client == null) { continue; } // from this point on, we know that client // has been successfully connected client.sendWelcomeMessage(); LOG.debug("New client connected: {}", client.getIp().getHostAddress()); } } catch (Exception ex) { LOG.error("Exception in acceptNewConnections(): " + ex.getMessage(), ex); } }
/** * 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 } } }
public static void main(String[] args) throws IOException { SocketChannel socketChannel = SocketChannel.open(); // 如果设置非阻塞模式,就可以在异步模式下调用connect(), read() 和write()了。可以进一步和Selector配合。之后章节会涉及 // socketChannel.configureBlocking(false); // 这个需要127.0.0.1的9999端口有进程在监听了,之后会将用ServerSocketChannel监听端口,做服务端 socketChannel.connect(new InetSocketAddress("127.0.0.1", 9999)); ByteBuffer buf = ByteBuffer.allocate(48); // 剩下的读写都可以参考fileChannel // 非阻塞模式时候可以如下等待 // while(! socketChannel.finishConnect() ){ // wait, or do something else... // } // 读取数据 // int bytesRead = socketChannel.read(buf); // System.out.println(bytesRead); // 写入数据 String newData = "New String to write to file..." + System.currentTimeMillis(); buf.clear(); buf.put(newData.getBytes()); buf.flip(); System.out.println("Start send message"); while (buf.hasRemaining()) { socketChannel.write(buf); } System.out.println("Finish send"); }
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); }
public SocketChannel getClientChannel(final boolean noTearDown) throws IOException { final List<String> listeners = m_config.getListenerAddresses(); final Random r = new Random(); final String listener = listeners.get(r.nextInt(listeners.size())); byte[] hashedPassword = ConnectionUtil.getHashedPassword(m_password); HostAndPort hNp = HostAndPort.fromString(listener); int port = Constants.DEFAULT_PORT; if (hNp.hasPort()) { port = hNp.getPort(); } final SocketChannel channel = (SocketChannel) ConnectionUtil.getAuthenticatedConnection( hNp.getHostText(), m_username, hashedPassword, port, null, ClientAuthHashScheme.getByUnencodedLength(hashedPassword.length))[0]; channel.configureBlocking(true); if (!noTearDown) { synchronized (m_clientChannels) { m_clientChannels.add(channel); } } return channel; }