سؤال

أنا مشوشة قليلا حول محجر في البرمجة C.

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

ما يحيرني هو توقيت البيانات وصوله إلى المقبس.

كيف يمكن أن أقول لكم عندما الحزم الوصول و كم حجم الحزمة, هل عليك أن تفعل كل رفع الأحمال الثقيلة نفسك ؟

بلدي الافتراض الأساسي هنا هو أن الحزم يمكن من طول متغير ، وذلك بمجرد البيانات الثنائية يبدأ الظهور أسفل المقبس ، كيف يمكنك أن تبدأ في بناء الحزم من ذلك ؟

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

المحلول

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

عند قراءة البيانات من مأخذ ، يمكنك طلب عدد معين من وحدات البايت.القراءة قد منع حتى العدد المطلوب من وحدات البايت التي يتم قراءتها ولكن لا يمكن العودة أقل بايت مما طلب.عندما يحدث هذا, يمكنك ببساطة إعادة قراءة الطالبة المتبقية بايت.

وهنا نموذجي C الدالة على قراءة عدد معين من وحدات البايت من مأخذ:

/* buffer points to memory block that is bigger than the number of bytes to be read */
/* socket is open socket that is connected to a sender */
/* bytesToRead is the number of bytes expected from the sender */
/* bytesRead is a pointer to a integer variable that will hold the number of bytes */
/*           actually received from the sender. */
/* The function returns either the number of bytes read, */
/*                             0 if the socket was closed by the sender, and */
/*                            -1 if an error occurred while reading from the socket */
int readBytes(int socket, char *buffer, int bytesToRead, int *bytesRead)
{
    *bytesRead = 0;
    while(*bytesRead < bytesToRead)
    {
        int ret = read(socket, buffer + *bytesRead, bytesToRead - *bytesRead);
        if(ret <= 0)
        {
           /* either connection was closed or an error occurred */
           return ret;
        }
        else
        {
           *bytesRead += ret;
        }
    }
    return *bytesRead;
}

نصائح أخرى

لذلك ، فإن الجواب على سؤالك يعتمد عادلة قليلا على ما إذا كنت تستخدم UDP أو TCP النقل الخاص بك.

UDP, يحصل على الحياة أبسط كثيرا في أنه يمكنك استدعاء recv/recvfrom/recvmsg مع حجم الحزمة تحتاج (كنت المرجح أن ترسل طول ثابت الحزم من المصدر على أي حال) ، وجعل افتراض أنه إذا كانت البيانات غير متوفرة, انها هناك في مضاعفات حزم طول الأحجام.(I. E.يمكنك الاتصال recv* مع حجم الخاص بك إرسال جانب حزمة وكنت المحددة.)

TCP الحياة يحصل قليلا أكثر إثارة للاهتمام - لغرض هذا التفسير سوف نفترض أن كنت تعرف كيفية استخدام المقبس () ، ربط(), الاستماع() وقبول() - وهذا الأخير هو كيف يمكنك الحصول على ملف واصف (FD) الخاص بك الصدد قدمت حديثا.

هناك طريقتان للقيام I/O عن مأخذ حجب ، التي تتصل قراءة(fd, buf, N) و القراءة يجلس هناك و ينتظر حتى كنت قد قرأت N بايت في buf - أو غير مؤمن ، التي لديك للتحقق (باستخدام select() أو استطلاع()) إذا كان FD للقراءة ثم لا قراءة().

عند التعامل مع TCP-اتصالات ، OS لا تدفع الانتباه إلى حزمة الأحجام ، حيث يعتبر تيار مستمر من البيانات ، وليس منفصلة حزمة الحجم قطع.

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

بقدر ما *NIX مأخذ البرمجة هي المعنية ، أنا أوصي دبليوريتشارد ستيفنز' "Unix برمجة الشبكات, Vol.1" (UNPv1) و "البرمجة المتقدمة في بيئة يونيكس" (APUE).الأول هو تومي فيما يتعلق الشبكة القائمة على البرمجة بغض النظر عن النقل, و هذا الأخير هو جيد للجميع حول كتاب البرمجة كما ينطبق على *NIX القائمة على البرمجة.أيضا, ابحث عن "TCP/IP المصورة" ، المجلدان 1 و 2.

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

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

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