private void writeWithHeader(SocketChannel channel, byte[] body) throws IOException { ByteBuffer header = ByteBuffer.allocate(4); header.putInt(body.length); header.flip(); int len = channel.write(header); assert (len == header.capacity()); channel.write(ByteBuffer.wrap(body)); }
@Test public void testGentleCloseDuringHandshake() throws Exception { InetSocketAddress address = startServer(version, null); SslContextFactory sslContextFactory = newSslContextFactory(); sslContextFactory.start(); SSLEngine sslEngine = sslContextFactory.newSSLEngine(address); sslEngine.setUseClientMode(true); NextProtoNego.put( sslEngine, new NextProtoNego.ClientProvider() { @Override public boolean supports() { return true; } @Override public void unsupported() {} @Override public String selectProtocol(List<String> protocols) { return null; } }); sslEngine.beginHandshake(); ByteBuffer encrypted = ByteBuffer.allocate(sslEngine.getSession().getPacketBufferSize()); sslEngine.wrap(BufferUtil.EMPTY_BUFFER, encrypted); encrypted.flip(); try (SocketChannel channel = SocketChannel.open(address)) { // Send ClientHello, immediately followed by TLS Close Alert and then by FIN channel.write(encrypted); sslEngine.closeOutbound(); encrypted.clear(); sslEngine.wrap(BufferUtil.EMPTY_BUFFER, encrypted); encrypted.flip(); channel.write(encrypted); channel.shutdownOutput(); // Read ServerHello from server encrypted.clear(); int read = channel.read(encrypted); encrypted.flip(); Assert.assertTrue(read > 0); // Cannot decrypt, as the SSLEngine has been already closed // Now if we read more, we should either read the TLS Close Alert, or directly -1 encrypted.clear(); read = channel.read(encrypted); // Sending a TLS Close Alert during handshake results in an exception when // unwrapping that the server react to by closing the connection abruptly. Assert.assertTrue(read < 0); } }
/** * Tests a bug in QuorumCnxManager that causes a spin lock when a negative value is sent. This * test checks if the connection is being closed upon a message with negative length. * * @throws Exception */ @Test public void testCnxManagerSpinLock() throws Exception { QuorumPeer peer = new QuorumPeer(peers, peerTmpdir[1], peerTmpdir[1], peerClientPort[1], 3, 1, 1000, 2, 2); QuorumCnxManager cnxManager = new QuorumCnxManager(peer); QuorumCnxManager.Listener listener = cnxManager.listener; if (listener != null) { listener.start(); } else { LOG.error("Null listener when initializing cnx manager"); } int port = peers.get(peer.getId()).electionAddr.getPort(); LOG.info("Election port: " + port); InetSocketAddress addr = new InetSocketAddress(port); Thread.sleep(1000); SocketChannel sc = SocketChannel.open(); sc.socket().connect(peers.get(new Long(1)).electionAddr, 5000); /* * Write id first then negative length. */ byte[] msgBytes = new byte[8]; ByteBuffer msgBuffer = ByteBuffer.wrap(msgBytes); msgBuffer.putLong(new Long(2)); msgBuffer.position(0); sc.write(msgBuffer); msgBuffer = ByteBuffer.wrap(new byte[4]); msgBuffer.putInt(-20); msgBuffer.position(0); sc.write(msgBuffer); Thread.sleep(1000); try { /* * Write a number of times until it * detects that the socket is broken. */ for (int i = 0; i < 100; i++) { msgBuffer.position(0); sc.write(msgBuffer); } fail("Socket has not been closed"); } catch (Exception e) { LOG.info("Socket has been closed as expected"); } peer.shutdown(); cnxManager.halt(); }
public void sendException(Exception e) { SocketChannel channel = this.socket.getChannel(); if (channel == null || !channel.isOpen()) { throw new IllegalStateException("cannot write to channel"); } try { if (e instanceof ClientError) { channel.write(charsetASCII.encode(Reply.CLIENT_ERROR.toString())); } else { channel.write(charsetASCII.encode(Reply.ERROR.toString())); } } catch (IOException ex) { } }
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(); } }
public int write(byte[] buf, int off, int len) throws IOException { if (!ready) { throw ISEnotusable; } int pos = 7; int current = len; // Force a blocking read. if (isComplete) { while (current > 0) { int digit = current % 16; current = current / 16; chunkLength[pos--] = HexUtils.HEX[digit]; } OutputWriter.flushChannel(socketChannel, ByteBuffer.wrap(chunkLength, pos + 1, 9 - pos)); } int nWrite = socketChannel.write(ByteBuffer.wrap(buf, off, len)); if (nWrite == len) { isComplete = true; OutputWriter.flushChannel(socketChannel, ByteBuffer.wrap(chunkLength, 8, 2)); OutputWriter.flushChannel(socketChannel, end.slice()); } else { isComplete = false; } return nWrite; }
private void write(SelectionKey key) throws IOException { SocketChannel ch = (SocketChannel) key.channel(); int count = 0; synchronized (pendingData) { List queue = (List) pendingData.get(ch); /** * Null exception alert: This can happen once a connection was established. Check send() for * more information. */ if (queue == null) return; while (!queue.isEmpty()) { ByteBuffer buf = (ByteBuffer) queue.get(0); ch.write(buf); count += buf.capacity() - buf.remaining(); if (buf.remaining() > 0) break; queue.remove(0); } if (queue.isEmpty()) key.interestOps(SelectionKey.OP_READ); } if (!listener.handleWrite(ch, count)) close(ch); }
/** Writes data pending message into a specific socket defined by the key */ private void write(SelectionKey key) throws IOException { SocketChannel socketChannel = (SocketChannel) key.channel(); synchronized (pendingWriteData) { List<ByteBuffer> queue = pendingWriteData.get(socketChannel); if (queue == null) { queue = new ArrayList<>(); pendingWriteData.put(socketChannel, queue); } // Write until there's no more data ... while (!queue.isEmpty()) { ByteBuffer buf = queue.get(0); socketChannel.write(buf); if (buf.remaining() > 0) { logger.finest("Write Buffer Full!"); break; } queue.remove(0); } if (queue.isEmpty()) { // All data written, change selector interest logger.finest("No more Data to write!"); key.interestOps(SelectionKey.OP_READ); } } }
private void processWritableKey(SelectionKey key) { CrawlURL url = (CrawlURL) key.attachment(); SocketChannel channel = (SocketChannel) key.channel(); ByteBuffer buffer = (ByteBuffer) url.getHandlerAttr(_REQUEST_BUFFER); try { // 发送http请求,若发送完成,取消OP_WRITE。 int writtenBytes = 0; for (int i = WRITE_SPIN_COUNT; i > 0; i--) { writtenBytes = channel.write(buffer); // write success if (writtenBytes != 0) { url.setHandlerAttr(_LAST_SEND_REQUEST_MILLIS, System.currentTimeMillis()); url.setHandlerAttr( _REQUEST_ALREADY_SEND_SIZE, (Integer) url.getHandlerAttr(_REQUEST_ALREADY_SEND_SIZE) + writtenBytes); url.setHandlerAttr( _REQUEST_SEND_TIMES, (Integer) url.getHandlerAttr(_REQUEST_SEND_TIMES) + 1); break; } } boolean reqSendFinished = !buffer.hasRemaining(); url.setHandlerAttr(_REQUEST_SEND_FINISHED, reqSendFinished); url.setHandlerAttr(_REQUEST_SEND_FINISHED_MILLIS, reqSendFinished); if (reqSendFinished) { url.removeHandlerAttr(_REQUEST_BUFFER); key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE); } } catch (IOException e) { logger.error("error send http request ! URL: " + url); cancelAndClose(key); url.setFetchStatus(FETCH_FAILED); url.getPipeline().resume(DefaultPipeline.EMPTY_MSG); } }
// Called when a peer we're trying to connect to sends us a message private void processNewPeer(SocketChannel c) throws IOException { ByteBuffer message = ChannelHelper.readBytes(c, 4); String recognize = utf8.decode(message).toString(); if (!recognize.equals("bam!")) { // Connected to something that wasn't a BAMPong client... c.close(); Peer p = new_peers.remove(c); log("Closing attempt to " + p.getName() + " got " + recognize); return; } // Assemble response ByteBuffer name = utf8.encode(nick); message = ByteBuffer.allocateDirect(name.limit() + 10); // id(4), port(4), name(2+limit) message.putInt(id); message.putInt(getPort()); ChannelHelper.putString(message, name); message.flip(); // Send message c.write(message); // Move socket to connected peers. Peer peer = new_peers.remove(c); peers.put(c, peer); sockets.put(peer, c); }
public boolean transmit(SocketChannel ch) throws IOException { if (buf == null) { byte[] data = serializeBinary(this); int len = data.length; buf = ByteBuffer.allocateDirect(len + 4); buf.put((byte) ((len >> 24) & 0xFF)); buf.put((byte) ((len >> 16) & 0xFF)); buf.put((byte) ((len >> 8) & 0xFF)); buf.put((byte) ((len) & 0xFF)); buf.put(data); buf.flip(); } if (ch.write(buf) < 0) { throw new IOException("Server went down"); } if (buf.hasRemaining()) { return false; } else { buf.flip(); return true; } }
private void write(SelectionKey key) throws IOException { SocketChannel socketChannel = (SocketChannel) key.channel(); synchronized (this.pendingData) { List queue = (List) this.pendingData.get(socketChannel); // Write until there's not more data ... while (!queue.isEmpty()) { ByteBuffer buf = (ByteBuffer) queue.get(0); socketChannel.write(buf); if (buf.remaining() > 0) { // ... or the socket's buffer fills up break; } queue.remove(0); } if (queue.isEmpty()) { // We wrote away all data, so we're no longer interested // in writing on this socket. Switch back to waiting for // data. key.interestOps(SelectionKey.OP_READ); } } }
private static void acceptClient(SocketChannel channel) throws IOException { buffer.clear(); buffer.put("you have already connected server!".getBytes()); buffer.flip(); channel.write(buffer); }
/* (non-Javadoc) * @see edu.tsinghua.lumaqq.qq.IPort#send(java.nio.ByteBuffer) */ public void send(ByteBuffer buffer) { try { channel.write(buffer); } catch (IOException e) { log.error(e.getMessage()); } }
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) { } } } } }
@Override public void writeAfterController(long timestamp) { jointCommand.clear(); jointCommand.putLong(estimatorTicksPerControlTick); jointCommand.putLong(timestamp); jointCommand.putLong(estimatorFrequencyInHz); for (int i = 0; i < joints.size(); i++) { OneDoFJoint joint = joints.get(i); if (fingerJointMap == null || !fingerJointMap.containsKey(joint.getName())) { if (joint.isUnderPositionControl()) jointCommand.putDouble(joint.getqDesired()); else jointCommand.putDouble(joint.getTau()); } else jointCommand.putDouble( fingerJointMap .get(joint.getName()) .getqDesired()); // fingers are always position controlled } jointCommand.flip(); try { while (jointCommand.hasRemaining()) { channel.write(jointCommand); } } catch (IOException e) { e.printStackTrace(); } }
public void send(byte[] d) throws IOException { ByteBuffer send = ByteBuffer.allocate(messageSize + 4); send.clear(); if (d.length + send.position() > send.capacity()) { out("!!!!!: Cant not send message, message length greater than max buffer size"); throw new RuntimeException( "!!!!!: Cant not send message, message length greater than max buffer size. capacity:" + send.capacity() + " , position:" + send.position() + "," + " data size:" + d.length); } if (this.pad) { send.putInt(d.length); } send.put(d); send.flip(); while (send.hasRemaining()) // write to channel { int bw = ssc.write(send); // out("bytes written: "+bw + " remaining: "+send.hasRemaining() +" r:"+send.position()+" v // "+send.limit()); } }
/** * 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); } } }
/** * 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); } } }
public void write(String line, SocketChannel socketChannel) { try { socketChannel.write(charset.encode(line)); } catch (Exception e) { log.info("error"); } }
private void offerWrite(QueuedWrite qw, Context cx) { if (writeQueue.isEmpty() && !qw.shutdown) { int written; try { written = clientChannel.write(qw.buf); } catch (IOException ioe) { // Hacky? We failed the immediate write, but the callback isn't set yet, // so go back and do it later queueWrite(qw); return; } if (log.isDebugEnabled()) { log.debug("Wrote {} to {} from {}", written, clientChannel, qw.buf); } if (qw.buf.hasRemaining()) { // We didn't write the whole thing. writeReady = false; queueWrite(qw); } else if (qw.onComplete != null) { qw.onComplete.call(cx, qw.onComplete, this, new Object[] {0, this, qw}); } } else { queueWrite(qw); } }
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); } } }
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"); }
/** * Writes bytes to the socket. * * @param buf byte buffer containing the bytes * @param offset offset into the buffer * @param length number of bytes to read * @param isEnd if the write is at a close. * @exception throws ClientDisconnectException if the connection is dropped */ @Override public void write(byte[] buf, int offset, int length, boolean isEnd) throws IOException { if (_s == null) { return; } try { _needsFlush = true; while (length > 0) { _writeBuffer.clear(); int sublen = Math.min(length, _writeBuffer.remaining()); _writeBuffer.put(buf, offset, sublen); _writeBuffer.flip(); _s.write(_writeBuffer); length -= sublen; offset += sublen; } _totalWriteBytes += length; } catch (IOException e) { IOException exn = ClientDisconnectException.create(this + ":" + e, e); try { close(); } catch (IOException e1) { } throw exn; } }
@Override public void write(Multiplexer multiplexer, SelectionKey key) throws Exception { try { _socket.write(_command); if (_command.position() == _command.limit()) { if (_state == ReceiverState.SEND_BYE) { close(multiplexer, key, true); // TODO: Check true } else { key.interestOps(SelectionKey.OP_READ); } } } catch (ClosedChannelException e) { /* From GridFTP v2 spec: "...the sender may choose not * to wait for 'BYE' acknowledgement. The sender is * allowed to close data channels immediately after * sending EOD, and the receiver may get a socket * error trying to send 'BYE' message back to the * sender". */ if (_state == ReceiverState.SEND_BYE) { close(multiplexer, key, true); // TODO: Check true } else { throw e; } } }
protected void writeBuffer(SocketChannel channel) throws IOException { synchronized (this.writeQueue) { ByteBuffer buffer = this.writeQueue.peek(); while (buffer != null) { writeSize += channel.write(buffer); if (buffer.hasRemaining()) { this.selectionKey.interestOps(selectionKey.interestOps() | SelectionKey.OP_WRITE); this.selectionKey.selector().wakeup(); break; } else { this.writeQueue.remove(); buffer = this.writeQueue.peek(); } } this.writeQueue.notifyAll(); } if (System.currentTimeMillis() - this.lastWriteTime > 1000) { writeSpeed = this.writeSize * 1.0 / (System.currentTimeMillis() - this.lastWriteTime); this.writeSize = 0; this.lastWriteTime = System.currentTimeMillis(); if (log.isDebugEnabled()) { log.debug( String.format( "Write speed %1.3f Kb/s on %s.", this.writeSpeed, this.listener.toString())); if (this.writeQueue.size() > 0) { log.warn( String.format( "Write buffer queue size:%s, on %s", this.writeQueue.size(), this.listener.toString())); } } } }
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); } }
/** * writes the contents of the buffer to the socket * * @param socketChannel the socket to publish the buffer to * @param approxTime an approximation of the current time in millis * @throws IOException */ private int writeBufferToSocket( @NotNull final SocketChannel socketChannel, final long approxTime) throws IOException { if (in.position() == 0) return 0; // if we still have some unwritten writer from last time lastSentTime = approxTime; out.limit((int) in.position()); final int len = socketChannel.write(out); if (LOG.isDebugEnabled()) LOG.debug("bytes-written=" + len); if (out.remaining() == 0) { out.clear(); in.clear(); } else { out.compact(); in.position(out.position()); in.limit(in.capacity()); out.clear(); } return len; }
/** * ������ѯ�ķ�ʽ����selector���Ƿ�����Ҫ������¼�������У�����д��� * * @throws IOException */ public void listen() { // ��ѯ����selector while (true) { int readyChannels = 0; try { readyChannels = selector.select(); if (readyChannels == 0) { continue; } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); if (selector != null) { try { selector.close(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } // ���selector��ѡ�е���ĵ���� Iterator ite = this.selector.selectedKeys().iterator(); while (ite.hasNext()) { SelectionKey key = (SelectionKey) ite.next(); // ɾ����ѡ��key,�Է��ظ����� ite.remove(); // �����¼����� if (key.isValid() && key.isConnectable()) { SocketChannel channel = (SocketChannel) key.channel(); // ����������ӣ���������� if (channel.isConnectionPending()) { try { channel.finishConnect(); // ���óɷ����� channel.configureBlocking(false); // ��������Ը����˷�����ϢŶ channel.write(ByteBuffer.wrap(new String("�����˷�����һ����Ϣ").getBytes())); // �ںͷ�������ӳɹ�֮��Ϊ�˿��Խ��յ�����˵���Ϣ����Ҫ��ͨ�����ö���Ȩ�ޡ� channel.register(this.selector, SelectionKey.OP_READ); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); if (channel != null) { try { channel.close(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } } } else if (key.isReadable()) { // ����˿ɶ����¼� read(key); } } } }
/** * 将字符串写入 * * @param line */ public void write(String line) { try { SocketChannel sk = (SocketChannel) selectionKey.channel(); sk.write(charset.encode(line)); } catch (Exception e) { log.info("error"); } }