netty server的read流程是怎样的

74次阅读
没有评论

共计 2924 个字符,预计需要花费 8 分钟才能阅读完成。

本篇内容主要讲解“netty server 的 read 流程是怎样的”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让丸趣 TV 小编来带大家学习“netty server 的 read 流程是怎样的”吧!

客户端发送数据过来的时候,netty 具体是怎么执行读取任务的。

仍然是从 NioEventLoop 开始,还是 NioEventLoop.processSelectedKey 这个方法,

private static void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
  final NioUnsafe unsafe = ch.unsafe();
  if (!k.isValid()) {
  // close the channel if the key is not valid anymore
  unsafe.close(unsafe.voidPromise());
  return;
  }

  try {
  int readyOps = k.readyOps();
  // Also check for readOps of 0 to workaround possible JDK bug which may otherwise lead
  // to a spin loop
  if ((readyOps (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
  unsafe.read();
  if (!ch.isOpen()) {
  // Connection already closed – no need to handle write.
  return;
  }
  }
  if ((readyOps SelectionKey.OP_WRITE) != 0) {
  // Call forceFlush which will also take care of clear the OP_WRITE once there is nothing left to write
  ch.unsafe().forceFlush();
  }
  if ((readyOps SelectionKey.OP_CONNECT) != 0) {
  // remove OP_CONNECT as otherwise Selector.select(..) will always return without blocking
  // See https://github.com/netty/netty/issues/924
  int ops = k.interestOps();
  ops = ~SelectionKey.OP_CONNECT;
  k.interestOps(ops);

  unsafe.finishConnect();
  }
  } catch (CancelledKeyException e) {
  unsafe.close(unsafe.voidPromise());
  }
  }

红色字体部分,unsafe.read(),进入到 AbstractNioByteChannel$NioByteUnsafe,要从 io 当中读取数据,首先需要分配一个 ByteBuf,这里涉及到了 2 个问题,1、从哪里分配内存,2、每次具体分配多大的内存。首先是第一个问题,首先大家需要了解(allocate 和 allocateDirect2 中方式的不同),具体的实现在 allocator.ioBuffer 当中,会根据平台不同,来决定能否直接分配系统内存。第二个问题,大家可以再看一下 allocHandle.record 方法,这个当中会根据当前从 io 当中读取的数据量,来决定后续分配内存的大小。然后就是从 socket 当中读取数据,写入 bytebuf,并触发一系列的 handler。

public void read() {
  final ChannelConfig config = config();
  final ChannelPipeline pipeline = pipeline();
  final ByteBufAllocator allocator = config.getAllocator();
  final int maxMessagesPerRead = config.getMaxMessagesPerRead();
  RecvByteBufAllocator.Handle allocHandle = this.allocHandle;
  if (allocHandle == null) {
  this.allocHandle = allocHandle = config.getRecvByteBufAllocator().newHandle();
  }
  if (!config.isAutoRead()) {
  removeReadOp();
  }

  ByteBuf byteBuf = null;
  int messages = 0;
  boolean close = false;
  try {
  int byteBufCapacity = allocHandle.guess();
  int totalReadAmount = 0;
  do {
  byteBuf = allocator.ioBuffer(byteBufCapacity);
  int writable = byteBuf.writableBytes();
  int localReadAmount = doReadBytes(byteBuf);
  if (localReadAmount = 0) {
  // not was read release the buffer
  byteBuf.release();
  close = localReadAmount
  break;
  }

  pipeline.fireChannelRead(byteBuf);
  byteBuf = null;

  if (totalReadAmount = Integer.MAX_VALUE – localReadAmount) {
  // Avoid overflow.
  totalReadAmount = Integer.MAX_VALUE;
  break;
  }

  totalReadAmount += localReadAmount;
  if (localReadAmount writable) {
  // Read less than what the buffer can hold,
  // which might mean we drained the recv buffer completely.
  break;
  }
  } while (++ messages maxMessagesPerRead);

  pipeline.fireChannelReadComplete();
  allocHandle.record(totalReadAmount);

  if (close) {
  closeOnRead(pipeline);
  close = false;
  }
  } catch (Throwable t) {
  handleReadException(pipeline, byteBuf, t, close);
  }
  }

到此,相信大家对“netty server 的 read 流程是怎样的”有了更深的了解,不妨来实际操作一番吧!这里是丸趣 TV 网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-16发表,共计2924字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)