مشاهدة مآخذ مع سطحي على ويندوز يضعهم في طريقة غير مؤمن

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

سؤال

التعليمة البرمجية التالية لا يعمل بشكل صحيح على ويندوز (ولكن لا على لينكس):

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setblocking(True)
    sock.connect(address)
    gobject.io_add_watch(
            sock.fileno(),
            gobject.IO_OUT | gobject.IO_ERR | gobject.IO_HUP,
            callback)

مقتطفات من تعليقات في أماكن مختلفة في مصدر سطحي, وغيرها من الأماكن التي يذكر هذا في Windows sockets وضع غير وضع الحجب خلال الاقتراع.نتيجة رد self.outgoing_cb ويسمى باستمرار و الكتابة مأخذ فشل مع رسالة الخطأ هذه:

[Errno 10035] A non-blocking socket operation could not be completed immediately

الدعوة sock.setblocking(True) قبل كتابة لا يبدو أن الالتفاف على هذا.عن طريق خفض الأولوية في الاقتراع ، وتجاهل رسالة الخطأ أنه يعمل كما هو متوقع ، ولكن يلقي بعيدا في العديد من المناسبات, و يستهلك الكثير من وحدة المعالجة المركزية.هل هناك طريقة للتغلب على هذا القيد في ويندوز ؟

التحديث

أود أن أشير إلى أن كل نقطة من الاقتراع POLLOUT هو أنه عندما تقوم بكتابة دعوة أنك لن تحصل على EAGAIN/EWOULDBLOCK.غريبة رسالة الخطأ التي حصلت وأعتقد سيكون ويندوز ما يعادل تلك 2 رموز الخطأ.وبعبارة أخرى, أنا الحصول على gobject.IO_OUT الأحداث عندما مأخذ لن اسمحوا لي أن أكتب بنجاح ، و وضعه في وضع الحجب زال يعطيني هذا غير مناسب خطأ.

آخر تحديث

على لينكس ، حيث يعمل هذا بشكل صحيح ، المقبس ليس تحولت إلى عدم عرقلة واسطة ، و تلقي IO_OUT, عندما المقبس سوف اسمحوا لي أن أكتب دون عرقلة أو رمي خطأ.انها هذه الوظيفة أريد أن الأفضل الاقتداء/استعادة ويندوز.

مزيد من الملاحظات

من man poll:

   poll()  performs a similar task to select(2): it waits for one of a set
   of file descriptors to become ready to perform I/O.
          POLLOUT
                 Writing now will not block.

من man select:

A file descriptor  is considered ready if it is possible to perform the corre‐
sponding I/O operation (e.g., read(2)) without blocking.
هل كانت مفيدة؟

المحلول

هل هناك مشكلة مع فعل غير مؤمن I/O ؟ يبدو من الغريب أن استخدام الاقتراع الحلقات إذا كنت تستخدم حجب I/O.

عندما أكتب مثل هذه البرامج لا تميل إلى القيام بما يلي:

  • العازلة بايت أريد أن ترسل إلى ملف واصف.

  • فقط أطلب IO_OUT (أو poll() ما يعادلها ، POLLOUT) الأحداث عندما قال العازلة غير فارغة.

  • عندما poll() (أو ما يعادلها) قد أشار أن كنت على استعداد لكتابة مسألة الكتابة.إذا كنت تحصل على EAGAIN/EWOULDBLOCK, إزالة بايت بنجاح كتب من المخزن المؤقت وانتظر المرة القادمة يمكنك الحصول على إشارة.إذا كنت بنجاح كتب كامل العازلة ، ثم وقف يسأل عن POLLOUT حتى لا spuriously يستيقظ.

(تخميني هو أن Win32 الارتباطات باستخدام WSAEventSelect و WaitForMultipleObjects() لمحاكاة poll(), ولكن النتيجة هي نفسها...)

أنا غير متأكد من كيفية النهج المطلوب مع حجب مآخذ العمل.أنت "الاستيقاظ" باستمرار لأنك طلبت لإيقاظك عندما يمكنك كتابة.كنت تريد فقط لتحديد عندما يكون لديك البيانات إلى الكتابة...ولكن بعد ذلك عندما يستيقظ لك ، فإن النظام لن اقول لك حقا كم البيانات يمكن أن تكتب دون عرقلة ، حتى أن هناك سبب وجيه لاستخدام غير مؤمن I/O.

نصائح أخرى

جيو يحتوي على GSocket, ، "lowlevel مأخذ الشبكة كائن" منذ 2.22.ولكن هذا بعد أن استدار إلى pygobject على ويندوز.

لست متأكدا إذا كان هذا يساعد (أنا لا يتقن مع استطلاع وظيفة أو MFC مآخذ لا أعرف الاقتراع هو شرط من البرنامج الخاص بك هيكل) ، حتى تأخذ هذا مع حبة الملح:

ولكن لتجنب عرقلة أو EAGAIN على الكتابة نستخدم حدد أيإضافة مقبس إلى كتابة مجموعة التي يتم تمريرها إلى تحديد ، إذا حدد() يعود مع rc=0 مأخذ يقبل ويكتب على الفور ...

كتابة حلقة نستخدمها في التطبيق لدينا هو (في شبة الكود):

set_nonblocking.
count= 0.
do {
   FDSET writefds;
   add skt to writefds.
   call select with writefds and a reaonsable timeout.
   if (select fails with timeout) {
       die with some error;
   } 

   howmany= send(skt, buf+count, total-count).
   if (howmany>0) {
       count+= howmany.
   }
} while (howmany>0 && count<total);

هل يمكن استخدام الملتوية, والتي تشمل دعم GTK (حتى على ويندوز) و سيتم التعامل مع جميع مختلف خطأ في ظروف غير مؤمن مآخذ على نظام التشغيل ويندوز مثل رفع.

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