كيف يمكن معرفة الواجهة التي استقبل المقبس الرسالة منها؟

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

  •  03-07-2019
  •  | 
  •  

سؤال

إذا كان المقبس مرتبطًا بـ IN6ADDR_ANY أو INADDR_ANY ويمكنك استخدام مكالمة مثل recvfrom() لتلقي الرسائل على المقبس.هل هناك طريقة لمعرفة الواجهة التي جاءت منها الرسالة؟

في حالة رسائل نطاق ارتباط IPv6، كنت آمل أن تكون الوسيطة من recvfrom() سيكون لديه scope_id تمت تهيئة الحقل إلى معرف الواجهة.لسوء الحظ تم ضبطه على 0 في برنامجي الاختباري

هل يعرف أحد طريقة لمعرفة هذه المعلومات؟

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

المحلول

وبصرف النظر عن ملزم للكل واجهة، وأنا لست على علم وسيلة مع عناوين IPv4، في حد ذاته.

وأضاف الإصدار IPv6 خيار مأخذ IPV6_PKTINFO لمعالجة هذا القصور. مع هذا الخيار في التنفيذ، سيتم إرجاع struct in6_pktinfo عن بيانات المساعدة.

نصائح أخرى

وكلية دبي للطالبات هو الحق، وسوف IPV6_PKTINFO العمل من أجل IPv6 على لينكس.

وعلاوة على ذلك، سوف IP_PKTINFO العمل ل IPv4 - يمكنك أن ترى التفاصيل في الملكية الفكرية manpage (7)

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

// sock is bound AF_INET socket, usually SOCK_DGRAM
// include struct in_pktinfo in the message "ancilliary" control data
setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt));
// the control data is dumped here
char cmbuf[0x100];
// the remote/source sockaddr is put here
struct sockaddr_in peeraddr;
// if you want access to the data you need to init the msg_iovec fields
struct msghdr mh = {
    .msg_name = &peeraddr,
    .msg_namelen = sizeof(peeraddr),
    .msg_control = cmbuf,
    .msg_controllen = sizeof(cmbuf),
};
recvmsg(sock, &mh, 0);
for ( // iterate through all the control headers
    struct cmsghdr *cmsg = CMSG_FIRSTHDR(&mh);
    cmsg != NULL;
    cmsg = CMSG_NXTHDR(&mh, cmsg))
{
    // ignore the control headers that don't match what we want
    if (cmsg->cmsg_level != IPPROTO_IP ||
        cmsg->cmsg_type != IP_PKTINFO)
    {
        continue;
    }
    struct in_pktinfo *pi = CMSG_DATA(cmsg);
    // at this point, peeraddr is the source sockaddr
    // pi->ipi_spec_dst is the destination in_addr
    // pi->ipi_addr is the receiving interface in_addr
}

ولها تم منذ بعض الوقت لقد تم القيام C / C ++ TCP / IP الترميز ولكن بقدر ما أتذكر على كل رسالة (أو مقبس المشتقة) يمكن أن تحصل في المعلومات رؤوس IP. وينبغي أن تتضمن هذه الرؤوس وعنوان المتلقي الذي سيكون IP واجهة تسألون عنه.

بعيدًا عن فتح مقبس منفصل على كل واجهة كما اقترح Glomek، فإن الطريقة الوحيدة التي أعرفها للقيام بذلك بشكل نهائي على Windows هي استخدام مقبس خام، على سبيل المثال،

  SOCKET s = socket(AF_INET, SOCK_RAW, IPPROTO_IP);

كل تلقي من هذا المقبس سيكون حزمة IP, ، والذي يحتوي على عنواني المصدر والوجهة.يتطلب البرنامج الذي أعمل عليه أن أضع المقبس في الوضع المختلط باستخدام خيار SIO_RCVALL.القيام بذلك يعني أنني أحصل على كل حزمة IP "تراها" الواجهة على الشبكة.يتطلب استخراج الحزم بشكل صريح لتطبيقي تصفية البيانات باستخدام العناوين والمنافذ الموجودة في رؤوس IP وTCP/UDP.من الواضح أن هذا ربما يكون أكثر من النفقات العامة التي تهتم بها.أذكر ذلك فقط لأقول هذا - لم أستخدم مطلقًا مقبسًا خامًا دون وضعه في الوضع المختلط.لذلك لست متأكدًا مما إذا كان بإمكانك ربطه بـ INADDR_ANY واستخدامه كمقبس عادي من تلك النقطة فصاعدًا أم لا.يبدو لي أنك تستطيع ذلك؛أنا فقط لم أحاول ذلك قط.

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

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