التابع select
الخاص بالصنف Kernel
في روبي
يستدعي select(2). ويقوم بمراقبة المصفوفة المعطاة المكونة من كائنات IO
، وينتظر حتى يكون أحد كائنات IO
جاهزًا للقراءة ، وجاهزا للكتابة، ويكون لها استثناءات معلقة (pending exceptions) على التوالي، ثم يعيد مصفوفة تحتوي على مصفوفات مكونة من تلك كائنات IO
السابقة. ستُعاد القيمة nil
إذا تم إعطاء قيمة للوسيط الاختياري timeout، ولم يكن هناك أي كائن IO
جاهزًا خلال timeout ثانية.
تراقب IO.select
المخزن المؤقت (buffer) لكائنات IO
لاختبار قابليتها للقراءة. إذا لم يكن المخزن المؤقت IO
فارغًا، فسيقوم IO.select
على الفور بالابلاغ عن جاهزية القراءة. هذا المراقبة لا تشمل إلا IO
كائنا. ولا تحدث للكائنات شبيهة IO مثل OpenSSL :: SSL :: SSLSocket.
أفضل طريقة لاستخدام IO.select
هي باستدعائها بعد توابع غير مُعطّلة (nonblocking methods) مثل read_nonblock
و write_nonblock
، وغيرهما. تطلق التوابع استثناء، والذي يُوسّع بواسطة IO::WaitReadable
أو IO::WaitWritable
. تقوم الوحدات (modules) بالابلاغ عن كيف ينبغي للمُستدعي (caller) الانتظار مع IO.select
. في حال إطلاق IO::WaitReadable
، فسيكون على المُستدعي أن ينتظر لأجل القراءة. وفي حال إطلاق IO::WaitWritable
، فيجب على المُستدعي أن ينتظر لأجل الكتابة.
لذلك، يمكن محاكاة حظر القراءة (readpartial
) باستخدام read_nonblock
و IO.select
على النحو التالي:
على نحو خاص، يُفضل الجمع بين التوابع غير المُعطلة و IO.select
للكائنات من صنف IO
، مثل OpenSSL::SSL::SSLSocket
. لديها طريقة to_io
لإرجاع الكائن IO
الأساسي. يستدعي IO.select
التابع to_io
لأجل الحصول على واصف الملف (file descriptor) المُنتظر.
هذا يعني أن الإبلاغ عن قابلية القراءة من طرف IO.select
لا تعني إمكانية القراءة من الكائن OpenSSL::SSL::SSLSocket
.
وعلى الأرجح أن OpenSSL::SSL::SSLSocket
تخزّن مؤقتا بعض البيانات. لا يرى IO.select
المخزن المؤقت. لذلك يمكن للتابع IO.select
أن يُعطل عندما لا يفعل OpenSSL::SSL::SSLSocket#readpartial
.
لكن توجد حالات أكثر تعقيدًا.
SSL هو بروتوكول، وهو عبارة عن تسلسل السجلات. تتكون السجلات من عدة بتات. لذا، يرسل الجانب البعيد من SSL سجلًا جزئيًا، يقوم IO.select
بالابلاغ عن إمكانية القراءة، ولكن لا يمكن لـ OpenSSL::SSL::SSLSocket
فك التشفير البايت، فيقوم OpenSSL::SSL::SSLSocket#readpartial
بالتعطيل.
يمكن أيضًا للجانب البعيد أن يطلب إعادة التفاوض حول SSL، والذي سيُجبر محرك SSL المحلي على كتابة بعض البيانات. هذا يعني أنّ OpenSSL::SSL::SSLSocket#readpartial
قد ينفذ نظام الاستدعاء write
ويمكنه الحجب. في مثل هذه الحالة، يطلق OpenSSL::SSL::SSLSocket#read_nonblock
الاستثناء IO::WaitWritable
بدلاً من التعطيل. لذلك، سيكون على المتصل الانتظار إلى حين جاهزية الكتابة كما هو مذكور أعلاه.
الجمع بين التوابع غير المُعطلة و IO.select
مفيد أيضًا للمجاري (streams) مثل tty ، والقنوات pipe socket عندما تقوم عدة عمليات بالقراءة من مجرى معيّن.
وأخيراً، لا يمكن لمطوري نواة لينكس (Linux kernel developers) أنّ قابلية القراءة select(2) تعني قابلية القراءة لـ read(2) حتى ولو في نفس العملية. انظر توثيق select(2) في نظام جنو / لينكس.
استدعاء IO.select
قبل IO#readpartial
يعمل بشكل جيد كالمعتاد. لكنه ليست الطريقة الأفضل لاستخدام IO.select
.
لا تُظهر قابلية الكتابة المُبلغ عنها من طرف select (2) عن عدد البايتات القابلة للكتابة. يتجمّد التابع IO#write
إلى أن حين كتابة السلسلة النصية المعطاة كاملة. لذلك ، يمكن أن يُعطل IO#write(two or more bytes)
بعد الابلاغ عن قابلية الكتابة من قبل IO.select
. لتجنب التعطيل، لا بد من IO#write_nonblock
.
يمكن محاكاة تعطيل الكتابة (write
) باستخدام write_nonblock
و IO.select
كما يلي: يجب أن يتم حفظ IO::WaitReadable
لأجل إعادة التفاوض SSL في OpenSSL::SSL::SSLSocket
.
Parameters¶
↑
read_array مصفوفة من كائنات IO
التي تنتظر إلى حين جاهزية القراءة. write_array مصفوفة من كائنات IO
، والتي تنتظر حتى جاهزية الكتابة error_array مصفوفة من كائنات IO
التي تنتظر الاستثناءات timeout قيمة عددية بالثواني
Example¶
↑
الناتج:
البنية العامة
select(read_array [, write_array [, error_array [, timeout]]]) → array or nil
المعاملات
read_array
write_array
error_array
timeout
القيمة المُعادة
أمثلة
مثال على استخدام التابع select
:
begin
result = io_like.read_nonblock(maxlen)
rescue IO::WaitReadable
IO.select([io_like])
retry
rescue IO::WaitWritable
IO.select(nil, [io_like])
retry
end
انظر أيضا
- التابع
require_relative
: عند استدعاء هذا التابع ستحاول روبي تحميل المكتبة المسماة في الوسيط المعطى string نسبة إلى مسار الملف المطلوب. إذا تعذر تحديد مسار الملف، سيُطلق خطأLoadError
. إذا تم تحميل ملف ستُعاد القيمةtrue
، وإلا فستُعاد false على خلاف ذلك. - التابع
set_trace_func
: يجعل التابع set_trace_func الوسيط المعطى proc كمتعقب (handler for tracing)، أو يعطل التعقب إن كان الوسيط يساويnil
.