recv(2)

الاسم
recv، recvfrom، recvmsg - استلام رسالة من مقبس

المكتبة
مكتبة سي المعيارية (libc، -lc)

موجز
#include <sys/socket.h>

ssize_t recv(size_t size;
                 int sockfd, void buf[size], size_t size,
                 int flags);
ssize_t recvfrom(size_t size;
                 int sockfd, void buf[restrict size], size_t size,
                 int flags,
                 struct sockaddr *_Nullable restrict src_addr,
                 socklen_t *_Nullable restrict addrlen);
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

الوصف
استدعاءات recv() و recvfrom() و recvmsg() تُستخدم لاستقبال رسائل من مقبس. يمكن استخدامها لاستقبال بيانات على كل من المقابس غير المتصلة والموجهة نحو الاتصال. تصف هذه الصفحة أولاً الميزات المشتركة لجميع استدعاءات النظام الثلاثة، ثم تصف الاختلافات بين الاستدعاءات.

الفرق الوحيد بين recv() و read(2) هو وجود flags. مع وسيطة flags صفرية، يكون recv() مكافئًا بشكل عام لـ read(2) (لكن انظر الملاحظات). أيضًا، الاستدعاء التالي

    recv(sockfd, buf, size, flags);

يكافئ

    recvfrom(sockfd, buf, size, flags, NULL, NULL);

تعيد جميع الاستدعاءات الثلاثة حجم الرسالة عند الإكمال بنجاح. إذا كانت الرسالة طويلة جدًا بحيث لا تتسع في المخزن المؤقت المقدم، فقد يتم تجاهل البايتات الزائدة اعتمادًا على نوع المقبس الذي تُستقبل منه الرسالة.

إذا لم تكن هناك رسائل متاحة في المقبس، تنتظر استدعاءات الاستقبال وصول رسالة، ما لم يكن المقبس غير محظور (انظر fcntl(2))، وفي هذه الحالة تُعاد القيمة -1 ويُضبط errno على EAGAIN أو EWOULDBLOCK. تعيد استدعاءات الاستقبال عادةً أي بيانات متاحة، حتى المقدار المطلوب، بدلاً من انتظار استلام المقدار الكامل المطلوب.

يمكن للتطبيق استخدام select(2) أو poll(2) أو epoll(7) لتحديد موعد وصول المزيد من البيانات على مقبس.

  معامل العلامات (flags)
تُشكل وسيطة flags عن طريق إجراء عملية OR على قيمة واحدة أو أكثر من القيم التالية:

MSG_CMSG_CLOEXEC (recvmsg() فقط؛ منذ Linux 2.6.23)
    يضبط علم الإغلاق عند التنفيذ لواصف الملف المستلم عبر واصف ملف نطاق UNIX باستخدام عملية SCM_RIGHTS (الموصوفة في unix(7)). هذا العلم مفيد لنفس أسباب علم O_CLOEXEC الخاص بـ open(2).

MSG_DONTWAIT (منذ لينكس 2.2)
    يمكّن التشغيل غير المحظور؛ إذا كانت العملية ستحظر، يفشل الاستدعاء مع EAGAIN أو EWOULDBLOCK. يوفر هذا سلوكًا مشابهًا لضبط علم O_NONBLOCK (عبر عملية fcntl(2) F_SETFL)، لكنه يختلف في أن MSG_DONTWAIT هو خيار لكل استدعاء، بينما O_NONBLOCK هو إعداد على وصف الملف المفتوح (انظر open(2))، والذي سيؤثر على جميع سلاسل التنفيذ في العملية المستدعية وكذلك العمليات الأخرى التي تحمل واصفات ملفات تشير إلى نفس وصف الملف المفتوح.

MSG_ERRQUEUE (منذ Linux 2.2)
    يحدد هذا العلم أنه يجب استقبال الأخطاء المُصطفة من قائمة انتظار أخطاء المقبس. يُمرر الخطأ في رسالة مساعدة بنوع يعتمد على البروتوكول (لـ IPv4 IP_RECVERR). يجب على المستخدم توفير مخزن مؤقت بحجم كافٍ. انظر cmsg(3) و ip(7) لمزيد من المعلومات. يُمرر حمولة الحزمة الأصلية التي تسببت في الخطأ كبيانات عادية عبر msg_iovec. يُمرر عنوان الوجهة الأصلي للرزمة التي تسببت في الخطأ عبر msg_name.

    يُقدم الخطأ في بنية sock_extended_err:

        #define SO_EE_ORIGIN_NONE    0
        #define SO_EE_ORIGIN_LOCAL   1
        #define SO_EE_ORIGIN_ICMP    2
        #define SO_EE_ORIGIN_ICMP6   3

        struct sock_extended_err
        {
            uint32_t ee_errno;   /* Error number */
            uint8_t  ee_origin;  /* Where the error originated */
            uint8_t  ee_type;    /* Type */
            uint8_t  ee_code;    /* Code */
            uint8_t  ee_pad;     /* Padding */
            uint32_t ee_info;    /* Additional information */
            uint32_t ee_data;    /* Other data */
            /* More data may follow */
        };

        struct sockaddr *SO_EE_OFFENDER(struct sock_extended_err *);

    يحتوي ee_errno على رقم errno للخطأ المُصطف. ee_origin هو رمز الأصل لمكان نشأة الخطأ. الحقول الأخرى خاصة بالبروتوكول. تعيد الماكرو SO_EE_OFFENDER مؤشرًا إلى عنوان كائن الشبكة حيث نشأ الخطأ، معطى مؤشرًا إلى الرسالة المساعدة. إذا كان هذا العنوان غير معروف، يحتوي عضو sa_family من sockaddr على AF_UNSPEC والحقول الأخرى من sockaddr غير معرفة. يُمرر حمولة الحزمة التي تسببت في الخطأ كبيانات عادية.

    بالنسبة للأخطاء المحلية، لا يُمرر أي عنوان (يمكن التحقق من ذلك باستخدام عضو cmsg_len من cmsghdr). لاستقبالات الأخطاء، يُضبط علم MSG_ERRQUEUE في msghdr. بعد تمرير خطأ، يُعاد توليد خطأ المقبس المعلق بناءً على الخطأ المُصطف التالي وسيُمرر في عملية المقبس التالية.

MSG_OOB
    يطلب هذا العلم استقبال بيانات خارج النطاق التي لن تُستقبل في تيار البيانات العادي. تضع بعض البروتوكولات البيانات المعجلة في رأس قائمة انتظار البيانات العادية، وبالتالي لا يمكن استخدام هذا العلم مع هذه البروتوكولات.

MSG_PEEK
    يتسبب هذا العلم في إعادة عملية الاستقبال للبيانات من بداية قائمة انتظار الاستقبال دون إزالة تلك البيانات من القائمة. وبالتالي، سيعيد استدعاء استقبال لاحق نفس البيانات.

MSG_TRUNC (منذ Linux 2.2)
    للمقابس الخام (AF_PACKET)، ورزم الإنترنت (منذ Linux 2.4.27/2.6.8)، وnetlink (منذ Linux 2.6.22)، ورزم UNIX وكذلك الحزم المتسلسلة (منذ Linux 3.4): إعادة الحجم الحقيقي للحزمة أو الرزمة، حتى عندما كانت أطول من المخزن المؤقت الممرر.

    للاستخدام مع مقابس تيار الإنترنت، انظر tcp(7).

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

  recvfrom()
يضع recvfrom() الرسالة المستلمة في المخزن المؤقت buf. يجب على المستدعي تحديد حجم المخزن المؤقت في size.

إذا كانت src_addr غير NULL، وكان البروتوكول الأساسي يوفر عنوان مصدر الرسالة، يتم وضع عنوان المصدر هذا في المخزن المؤقت الذي تشير إليه src_addr. في هذه الحالة، تكون addrlen معلمة قيمة-نتيجة. قبل الاستدعاء، يجب تهيئتها بحجم المخزن المؤقت المرتبط بـ src_addr. عند العودة، يحدّث addrlen ليحتوي على الحجم الفعلي لعنوان المصدر. ًيُقتطع العنوان المُرجع إذا كان المخزن المؤقت المُقدّم صغيرًا جدًّا؛ وفي هذه الحالة، سيعيد addrlen قيمة أكبر من تلك التي تم تزويدها للاستدعاء.

إذا لم يكن المستدعي مهتمًا بعنوان المصدر، فيجب تحديد src_addr و addrlen كقيمة NULL.

  recv()
عادةً ما يُستخدم استدعاء recv() فقط على مقبس موصل (انظر connect(2)). وهو مكافئ للاستدعاء:

    recvfrom(fd, buf, size, flags, NULL, NULL);

  recvmsg()
يستخدم استدعاء recvmsg() بنية msghdr لتقليل عدد الوسائط المقدمة مباشرة. تُعرف هذه البنية كما يلي في <sys/socket.h>:

    struct msghdr {
        void         *msg_name;       /* عنوان اختياري */
        socklen_t     msg_namelen;    /* حجم العنوان */
        struct iovec *msg_iov;        /* مصفوفة توزيع/تجميع */
        size_t        msg_iovlen;     /* عدد العناصر في msg_iov */
        void         *msg_control;    /* بيانات مساعدة، انظر أدناه */
        size_t        msg_controllen; /* حجم مخزن البيانات المساعدة */
        int           msg_flags;      /* أعلام على الرسالة المستلمة */
    };

يشير حقل msg_name إلى مخزن مخصص من قبل المستدعي يُستخدم لإرجاع عنوان المصدر إذا كان المقبس غير موصل. يجب على المستدعي تعيين msg_namelen إلى حجم هذا المخزن قبل هذا الاستدعاء؛ عند العودة من استدعاء ناجح، سيحتوي msg_namelen على حجم العنوان المُعاد. إذا لم يكن التطبيق بحاجة لمعرفة عنوان المصدر، يمكن تحديد msg_name كقيمة NULL.

تصف الحقول msg_iov و msg_iovlen مواقع التوزيع والتجميع، كما نوقش في readv(2).

يشير حقل msg_control، الذي له حجم msg_controllen، إلى مخزن للرسائل الأخرى المتعلقة بالتحكم في البروتوكول أو البيانات المساعدة المتنوعة. عند استدعاء recvmsg()، يجب أن يحتوي msg_controllen على حجم المخزن المتاح في msg_control؛ عند العودة من استدعاء ناجح، سيحتوي على حجم تسلسل رسائل التحكم.

الرسائل تكون بالشكل:

    struct cmsghdr {
        size_t cmsg_len;    /* عدد بايتات البيانات، بما في ذلك الرأس
                               (النوع هو socklen_t في POSIX) */
        int    cmsg_level;  /* البروتوكول المصدر */
        int    cmsg_type;   /* نوع خاص بالبروتوكول */
    /* يتبعه
        unsigned char cmsg_data[]; */
    };

يجب الوصول إلى البيانات المساعدة فقط من خلال وحدات الماكرو المعرفة في cmsg(3).

كمثال، تستخدم لينكس آلية البيانات المساعدة هذه لتمرير الأخطاء الموسعة، خيارات IP، أو واصفات الملفات عبر مقابس نطاق UNIX. لمزيد من المعلومات حول استخدام البيانات المساعدة في نطاقات المقابس المختلفة، انظر unix(7) و ip(7).

يتم تعيين حقل msg_flags في msghdr عند عودة recvmsg(). يمكن أن يحتوي على عدة أعلام:

MSG_EOR
    يشير إلى نهاية السجل؛ البيانات المُعادة أكملت سجلًا (بشكل عام، يُستخدم مع مقابس من نوع SOCK_SEQPACKET).

MSG_TRUNC
    يشير إلى أن الجزء الخلفي من مخطط البيانات تم تجاهله لأن مخطط البيانات كان أكبر من المخزن المقدم.

MSG_CTRUNC
    يشير إلى أن بعض بيانات التحكم تم تجاهلها بسبب نقص المساحة في المخزن للبيانات المساعدة.

MSG_OOB
    يُعاد للإشارة إلى أن بيانات عاجلة أو خارج النطاق تم استلامها.

MSG_ERRQUEUE
    يشير إلى أنه لم يتم استلام أي بيانات ولكن خطأ موسع من قائمة أخطاء المقبس.

MSG_CMSG_CLOEXEC (منذ لينكس 2.6.23)
    يشير إلى أن MSG_CMSG_CLOEXEC تم تحديده في وسيطة flags لـ recvmsg().

قيمة الإرجاع
تُعيد هذه الاستدعاءات عدد البايتات المستلمة، أو -1 إذا حدث خطأ. في حالة حدوث خطأ، يتم تعيين errno للإشارة إلى الخطأ.

عندما يقوم نظير مقبس التدفق بإغلاق منظم، ستكون القيمة المُعادة 0 (الإرجاع التقليدي "نهاية الملف").

تسمح مقابس مخططات البيانات في نطاقات مختلفة (مثل نطاقات UNIX والإنترنت) بمخططات بيانات بحجم صفر. عند استلام مثل هذا المخطط، تكون القيمة المُعادة 0.

قد تُعاد القيمة 0 أيضًا إذا كان عدد البايتات المطلوب استلامها من مقبس تدفق هو 0.

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

EAGAIN أو EWOULDBLOCK
    المقبس مُعلّم كغير محظور وعملية الاستقبال ستحظر، أو ضُبط مهلة استقبال وانتهت المهلة قبل استلام البيانات. يسمح POSIX.1 بإرجاع أي من الخطأين لهذه الحالة، ولا يتطلب أن تكون هذه الثوابت بنفس القيمة، لذا يجب على التطبيق المحمول التحقق من كلا الاحتمالين.

EBADF
    الوسيطة sockfd هي واصف ملف غير صالح.

ECONNREFUSED
    رفض مضيف بعيد السماح باتصال الشبكة (عادةً لأنه لا يشغل الخدمة المطلوبة).

EFAULT
    مؤشرات المخزن المؤقت للاستقبال تشير إلى خارج مساحة عنوان العملية.

EINTR
    قُطعت عملية الاستقبال بتسليم إشارة قبل توفر أي بيانات؛ انظر signal(7).

EINVAL
    مُرر معامل غير صالح.

ENOMEM
    تعذر تخصيص ذاكرة لـ recvmsg().

ENOTCONN
    المقبس مرتبط ببروتوكول موجه للاتصال ولم يُوصل (انظر connect(2) و accept(2)).

ENOTSOCK
    واصف الملف sockfd لا يشير إلى مقبس.

الإصدارات
وفقًا لـ POSIX.1، يجب أن يكون حقل msg_controllen في بنية msghdr من النوع socklen_t، وحقل msg_iovlen من النوع int، لكن glibc حاليًا يكتب كليهما كـ size_t.

المعايير
POSIX.1-2024.

التاريخ
POSIX.1-2001،‏ 4.2BSD.

يصف POSIX.1 فقط الأعلام MSG_OOB و MSG_PEEK و MSG_WAITALL.

ملاحظات
إذا كان هناك مخطط بيانات بحجم صفري معلق، فإن read(2) و recv() مع وسيطة flags بقيمة صفر توفر سلوكًا مختلفًا. في هذه الحالة، لا تأثير لـ read(2) (يبقى مخطط البيانات معلقًا)، بينما تستهلك recv() مخطط البيانات المعلق.

انظر recvmmsg(2) للحصول على معلومات حول استدعاء نظام خاص بلينكس يمكن استخدامه لاستقبال مخططات بيانات متعددة في استدعاء واحد.

أمثلة
مثال على استخدام recvfrom() موضح في getaddrinfo(3).

انظر أيضًا
fcntl(2), getsockopt(2), read(2), recvmmsg(2), select(2), shutdown(2), socket(2), cmsg(3), sockatmark(3), ip(7), ipv6(7), socket(7), tcp(7), udp(7), unix(7)

ترجمة
تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>

هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 (https://www.gnu.org/licenses/gpl-3.0.html) أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.

إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.