الفرق بين المراجعتين لصفحة: «Ruby/Kernel/select»
لا ملخص تعديل |
لا ملخص تعديل |
||
سطر 26: | سطر 26: | ||
على الأرجح أنّ <code>OpenSSL::SSL::SSLSocket</code> تخزّن مؤقتا بعض البيانات. لكن لا يرى <code>IO.select</code> المخزن المؤقت (buffer). لذلك يمكنه أن يُعطل (block) عندما لا يفعل <code>OpenSSL::SSL::SSLSocket#readpartial</code>. لكن توجد حالات أكثر تعقيدًا. | على الأرجح أنّ <code>OpenSSL::SSL::SSLSocket</code> تخزّن مؤقتا بعض البيانات. لكن لا يرى <code>IO.select</code> المخزن المؤقت (buffer). لذلك يمكنه أن يُعطل (block) عندما لا يفعل <code>OpenSSL::SSL::SSLSocket#readpartial</code>. لكن توجد حالات أكثر تعقيدًا. | ||
SSL | SSL بروتوكول، وهو عبارة عن تسلسل للسجلات (sequence of records). تتكون السجلات من عدة بتات. لذا، يرسل الجانب البعيد من SSL سجلًا جزئيًا، ويقوم <code>IO.select</code> بالابلاغ عن إمكانية القراءة، ولكن لا يمكن لـ <code>OpenSSL::SSL::SSLSocket</code> فك تشفير البايتات، فيقوم <code>OpenSSL::SSL::SSLSocket#readpartial</code> بالتعطيل. | ||
يمكن أيضًا للجانب البعيد أن يطلب إعادة تفاوض أمني SSL، والذي سيُجبر محرك SSL المحلي على كتابة بعض البيانات. هذا يعني أنّ <code>OpenSSL::SSL::SSLSocket#readpartial</code> قد يستدعي نظام الاستدعاء <code>write</code> ويمكنه التعطيل في مثل هذه الحالة، يُطلق <code>OpenSSL::SSL::SSLSocket#read_nonblock</code> الاستثناء <code>IO::WaitWritable</code>، بدلاً من التعطيل. لذلك، سيكون على المتصل الانتظار إلى حين جاهزية الكتابة كما هو مذكور أعلاه. | يمكن أيضًا للجانب البعيد أن يطلب إعادة تفاوض أمني SSL، والذي سيُجبر محرك SSL المحلي على كتابة بعض البيانات. هذا يعني أنّ <code>OpenSSL::SSL::SSLSocket#readpartial</code> قد يستدعي نظام الاستدعاء <code>write</code>، ويمكنه التعطيل في مثل هذه الحالة، يُطلق <code>OpenSSL::SSL::SSLSocket#read_nonblock</code> الاستثناء <code>IO::WaitWritable</code>، بدلاً من التعطيل. لذلك، سيكون على المتصل الانتظار إلى حين جاهزية الكتابة كما هو مذكور أعلاه. | ||
الجمع بين التوابع غير المُعطلة و <code>IO.select</code> مفيد أيضًا للمجاري (streams) مثل <code>tty</code> ، والقنوات (pipe socket)، عندما تقوم عدة عمليات بالقراءة من مجرى معيّن. | الجمع بين التوابع غير المُعطلة و <code>IO.select</code> مفيد أيضًا للمجاري (streams) مثل <code>tty</code> ، والقنوات (pipe socket)، عندما تقوم عدة عمليات بالقراءة من مجرى معيّن. | ||
سطر 36: | سطر 36: | ||
استدعاء <code>IO.select</code> قبل <code>IO#readpartial</code> يعمل بشكل جيد كالمعتاد. لكنه ليس الطريقة المثلى لاستخدام <code>IO.select</code>. | استدعاء <code>IO.select</code> قبل <code>IO#readpartial</code> يعمل بشكل جيد كالمعتاد. لكنه ليس الطريقة المثلى لاستخدام <code>IO.select</code>. | ||
لا تُظهر قابلية الكتابة المُبلغ عنها من طرف <code>select (2)</code> عن عدد البايتات القابلة للكتابة. يتعطّل التابع <code>IO#write</code> إلى حين كتابة السلسلة النصية المعطاة كاملة. لذلك ، يمكن أن يُعطل <code>IO#write(two or more bytes)</code> بعد الابلاغ عن قابلية الكتابة من قبل <code>IO.select</code>. لتجنب التعطيل، لا بد من استخدام<code>IO#write_nonblock</code>. | لا تُظهر قابلية الكتابة المُبلغ عنها من طرف <code>select(2)</code> عن عدد البايتات القابلة للكتابة. يتعطّل التابع <code>IO#write</code> إلى حين كتابة السلسلة النصية المعطاة كاملة. لذلك ، يمكن أن يُعطل <code>IO#write(two or more bytes)</code> بعد الابلاغ عن قابلية الكتابة من قبل <code>IO.select</code>. لتجنب التعطيل، لا بد من استخدام<code>IO#write_nonblock</code>. | ||
يمكن محاكاة تعطيل الكتابة (<code>write</code>) باستخدام <code>write_nonblock</code> و <code>IO.select</code> كما يلي: يجب أن يتم حفظ <code>IO::WaitReadable</code> لأجل إعادة التفاوض الأمني SSL في <code>OpenSSL::SSL::SSLSocket</code>. <syntaxhighlight lang="ruby">while 0 < string.bytesize | يمكن محاكاة تعطيل الكتابة (<code>write</code>) باستخدام <code>write_nonblock</code> و <code>IO.select</code> كما يلي: يجب أن يتم حفظ <code>IO::WaitReadable</code> لأجل إعادة التفاوض الأمني SSL في <code>OpenSSL::SSL::SSLSocket</code>. <syntaxhighlight lang="ruby">while 0 < string.bytesize | ||
سطر 66: | سطر 66: | ||
قيمة عددية تمثل عدد ثواني الانتظار. | قيمة عددية تمثل عدد ثواني الانتظار. | ||
==القيمة المُعادة== | ==القيمة المُعادة== | ||
يعيد مصفوفة تحتوي على مصفوفات مكونة من كائنات <code>IO</code> السابقة. | يعيد مصفوفة تحتوي على مصفوفات مكونة من كائنات <code>IO</code> السابقة. أما إذا تم إعطاء قيمة للوسيط الاختياري <code>timeout</code>، ولم يكن هناك أي كائن <code>IO</code> جاهز خلال <code>timeout</code> ثانية، فستُعاد القيمة <code>nil</code>. | ||
==أمثلة== | ==أمثلة== | ||
سطر 96: | سطر 96: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==انظر أيضا== | ==انظر أيضا== | ||
* | * صفحة الصنف <code>[[Ruby/IO|IO]]</code> | ||
==مصادر== | ==مصادر== | ||
*[http://ruby-doc.org/core-2.5.1/Kernel.html#method-i-select قسم التابع select في الصنف Kernel في توثيق روبي الرسمي.] | *[http://ruby-doc.org/core-2.5.1/Kernel.html#method-i-select قسم التابع select في الصنف Kernel في توثيق روبي الرسمي.] |
مراجعة 16:11، 22 أكتوبر 2018
يستدعي هذا التابع نظام الاستدعاء select(2)
. ويقوم بمراقبة (monitors) المصفوفات المعطاة المكونة من كائنات 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
على النحو التالي:
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
عمومًا، يُفضل الجمع بين التوابع غير المُعطلة و 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
المخزن المؤقت (buffer). لذلك يمكنه أن يُعطل (block) عندما لا يفعل OpenSSL::SSL::SSLSocket#readpartial
. لكن توجد حالات أكثر تعقيدًا.
SSL بروتوكول، وهو عبارة عن تسلسل للسجلات (sequence of records). تتكون السجلات من عدة بتات. لذا، يرسل الجانب البعيد من 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
.
while 0 < string.bytesize
begin
written = io_like.write_nonblock(string)
rescue IO::WaitReadable
IO.select([io_like])
retry
rescue IO::WaitWritable
IO.select(nil, [io_like])
retry
end
string = string.byteslice(written..-1)
end
البنية العامة
select(read_array [, write_array [, error_array [, timeout]]]) → array or nil
المعاملات
read_array
مصفوفة من كائنات IO
التي تنتظر إلى حين جاهزية القراءة.
write_array
مصفوفة من كائنات IO
، والتي تنتظر حتى جاهزية الكتابة
error_array
مصفوفة من كائنات IO
التي تنتظر الاستثناءات
timeout
قيمة عددية تمثل عدد ثواني الانتظار.
القيمة المُعادة
يعيد مصفوفة تحتوي على مصفوفات مكونة من كائنات IO
السابقة. أما إذا تم إعطاء قيمة للوسيط الاختياري timeout
، ولم يكن هناك أي كائن IO
جاهز خلال timeout
ثانية، فستُعاد القيمة nil
.
أمثلة
مثال على استخدام التابع select
:
rp, wp = IO.pipe
mesg = "ping "
100.times {
# IO.select follows IO#read. Not the best way to use IO.select.
rs, ws, = IO.select([rp], [wp])
if r = rs[0]
ret = r.read(5)
print ret
case ret
when /ping/
mesg = "pong\n"
when /pong/
mesg = "ping "
end
end
if w = ws[0]
w.write(mesg)
end
}
الناتج:
ping pong
ping pong
ping pong
(snipped)
ping
انظر أيضا
- صفحة الصنف
IO