حول كتابة المخزن المؤقت في برمجة الشبكات العامة

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

سؤال

أنا أكتب الخادم باستخدام boost.asio. لقد قرأت وكتب المخزن المؤقت لكل اتصال واستخدام وظيفة القراءة / الكتابة غير المتزامة (async_write_some / async_read_some).

مع قراءة العازلة و async_read_some, ، ليس هناك مشكلة. مجرد استدعاء async_read_some وظيفة على ما يرام لأن قراءة المخزن المؤقت تتم قراءتها فقط في معالج القراءة (يعني في نفس الخيط عادة).

ولكن، يجب الوصول إلى المخزن المؤقت للكتابة من العديد من المواضيع حتى تحتاج إلى أن تكون مؤمنة للتعديل.

السؤال الأول!

هل هناك أي طريقة لتجنب القفل من أجل الكتابة العازلة؟

أكتب رزمتي الخاصة في عازلة مكدس ونسخها إلى المخزن المؤقت للكتابة. ثم اتصل async_write_some وظيفة لإرسال الحزمة. بهذه الطريقة، إذا أرسلت حزمتين في المسلسل، هل هو بخير async_write_some وظيفة مرتين؟

السؤال الثاني!

ما هي الطريقة الشائعة للكتابة غير المتزونة في برمجة المقبس؟

شكرا للقراءة.

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

المحلول

الإجابة رقم 1:

أنت صحيح أن القفل هو نهج قابل للحياة، ولكن هناك طريقة أبسط بكثير للقيام بكل هذا. بوست لديها بناء صغير لطيف في آسيو يسمى strand. وبعد سيتم تسلسل أي رد اتصال باستخدام Strand، مضمونة، بغض النظر عن مؤشر ترابط ينفذ رد الاتصال. في الأساس، فإنه يعالج أي قفل لك.

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

char buffer_to_write[256];  // shared among threads

/* ... in thread 1 ... */
memcpy(buffer_to_write, packet_1, std::min(sizeof(packet_1), sizeof(buffer_to_write)));
my_socket.async_write_some(boost::asio::buffer(buffer_to_write, sizeof(buffer_to_write)), &my_callback);

/* ... in thread 2 ... */
memcpy(buffer_to_write, packet_2, std::min(sizeof(packet_2), sizeof(buffer_to_write)));
my_socket.async_write_some(boost::asio::buffer(buffer_to_write, sizeof(buffer_to_write)), &my_callback);

هناك، أنت تقاسم العازلة الفعلية للكتابة الفعلية (buffer_to_write). إذا فعلت شيئا مثل هذا بدلا من ذلك، فستكون بخير:

/* A utility class that you can use */
class PacketWriter
{
private:
  typedef std::vector<char>  buffer_type;

  static void WriteIsComplete(boost::shared_ptr<buffer_type> op_buffer, const boost::system::error_code& error, std::size_t bytes_transferred)
  {
    // Handle your write completion here
  }

public:
  template<class IO>
  static bool WritePacket(const std::vector<char>& packet_data, IO& asio_object)
  {
    boost::shared_ptr<buffer_type> op_buffer(new buffer_type(packet_data));

    if (!op_buffer)
    {
      return (false);
    }

    asio_object.async_write_some(boost::asio::buffer(*op_buffer), boost::bind(&PacketWriter::WriteIsComplete, op_buffer, boost::asio::placeholder::error, boost::asio::placeholder::bytes_transferred));
  }
};

/* ... in thread 1 ... */
PacketWriter::WritePacket(packet_1, my_socket);

/* ... in thread 2 ... */
PacketWriter::WritePacket(packet_2, my_socket);

هنا، سيساعد ذلك إذا مرت حبيبتك في WritePacket أيضا. تحصل على هذه الفكرة على الرغم من.

الإجابة رقم 2:

أعتقد أنك تأخذ بالفعل نهج جيد للغاية. اقتراح واحد سأقدمه هو استخدام async_write بدلا من async_write_some بحيث تكون مضمونا، يتم كتابة المخزن المؤقت بأكمله قبل أن يتم استدعاء اتصالك.

نصائح أخرى

آسف ولكن لديك اثنين من الخيارات:

  1. Serialise بيان الكتابة، إما مع الأقفال، أو أفضل بدء خيط كاتب منفصل يقرأ الطلبات من قائمة الانتظار، يمكن أن تكتسب مؤشرات الترابط الأخرى طلبات مكدس في قائمة الانتظار دون الكثير من الخلاف (ستكون هناك حاجة إلى بعض المكشوف).

  2. إعطاء كل كتاب الكتابة مقبس خاص به! هذا هو في الواقع الحل الأفضل إذا كان البرنامج في الطرف الآخر من السلك يمكن أن يدعمه.

يمكنك ربط التعديلات الخاصة بك وأداءها على البيانات في معالج الكتابة.

من المحتمل أن تكون الشبكة هي الأبدية أبطأ جزء من الأنبوب (على افتراض أن التعديل ليس باهظ الثمن)، بحيث يمكنك إجراء تعديلات أثناء إرسال طبقة المقبس البيانات السابقة.

تقوم Incase، أنت تتعامل مع عدد كبير من العملاء مع الاتصال / عدم فصل متكرر إلقاء نظرة على منافذ إكمال IO أو آلية مماثلة.

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