جافا NIO تحديد العوائد () من دون مفاتيح المختارة - لماذا؟

StackOverflow https://stackoverflow.com/questions/204186

  •  03-07-2019
  •  | 
  •  

سؤال

في كتابة بعض رمز اختبار قد وجدت لي أن Selector.select () يمكن العودة دون Selector.selectedKeys () تحتوي على أي من مفاتيح لهذه العملية. يحدث هذا في حلقة ضيقة عندما أسجل قناة إد استعرض () مع

SelectionKey.OP_READ | SelectionKey.OP_CONNECT

وكما عمليات الفائدة.

ووفقا للمستندات، حدد () يجب أن تعود في الحالات التالية:

1) وهناك القنوات التي يمكن اتخاذ إجراءات بشأنها.

2) أنت تدعو صراحة Selector.wakeup () - يتم اختيار أي مفاتيح

.

و3) أنت صراحة Thread.interrupt () في موضوع القيام تحديد () - يتم اختيار أي مفاتيح

إذا أحصل على أي مفاتيح بعد تحديد () يجب أن تكون في حالة (2) و (3). ومع ذلك، قانون بلدي لا يدعو التنبيه () أو يقطع () لبدء هذه العوائد.

وأي أفكار حول ما يسبب هذا السلوك؟

هل كانت مفيدة؟

المحلول

والجواب باختصار: إزالة OP_CONNECT من قائمة العمليات كنت مهتما في لاتصال المقبولة - اتصال مقبول متصلا بالفعل

وتمكنت من إعادة إنشاء المشكلة، والتي قد تكون بالضبط ما يحدث لك:

import java.net.*;
import java.nio.channels.*;


public class MyNioServer {
  public static void main(String[] params) throws Exception {
    final ServerSocketChannel serverChannel = ServerSocketChannel.open();
    serverChannel.configureBlocking(true);
    serverChannel.socket().bind(new InetSocketAddress("localhost", 12345));
    System.out.println("Listening for incoming connections");
    final SocketChannel clientChannel = serverChannel.accept();
    System.out.println("Accepted connection: " + clientChannel);


    final Selector selector = Selector.open();
    clientChannel.configureBlocking(false);
    final SelectionKey clientKey = clientChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_CONNECT);
    System.out.println("Selecting...");
    System.out.println(selector.select());
    System.out.println(selector.selectedKeys().size());
    System.out.println(clientKey.readyOps());
  }
}

وبعد أن يتلقى الخادم أعلاه اتصال، وselect() أولا جدا على اتصال يخرج دون عرقلة وعدم وجود مفاتيح مع عمليات جاهزة. أنا لا أعرف لماذا يتصرف جافا بهذه الطريقة، ولكن يبدو كثير من الناس الحصول على لعض من هذا السلوك.

والنتيجة هي نفسها على الشمس JVM 1.5.0_06 على نظام التشغيل Windows XP وكذلك JVM الشمس 1.5.0_05 و1.4.2_04 على لينكس 2.6.

نصائح أخرى

والسبب هو أن OP_CONNECT وOP_WRITE هي نفس الشيء تحت غطاء محرك السيارة، لذلك يجب أن لا تكون مسجلة على حد سواء في وقت واحد (كما سبق OP_ACCEPT وOP_READ)، ويجب أن لا تكون مسجلة لOP_CONNECT على الإطلاق عند توصيل القناة بالفعل ، كما هو الحال في هذه القضية، بعد أن تم قبول.

وOP_WRITE هو على استعداد دائما تقريبا، إلا عندما المخزن المؤقت إرسال مأخذ في البريد نواة مليء، لذا يجب عليك تسجيل فقط لأنه بعد الحصول على الكتابة طول صفري. لذلك من خلال تسجيل قناة متصلة بالفعل لOP_CONNECT, كنت مسجلا حقا لOP_WRITE, الذي كان على استعداد، لذلك select() حصلت على تشغيلها.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top