كيفية الحصول على بلدي غير الاسترجاع شبكة ip عنوان في C ؟

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

سؤال

من أجل التواصل بين البلدين المضيفين ، أنا في حاجة الى ارسال عنوان IP من المضيف إلى موقع آخر.المشكلة هي أنه إذا كنت طلب عنوان IP الخاص بي ، قد يكون من أن أعود إلى بلدي المحلية الاسترجاع IP addres (127.x.x.x) , شبكة (ethernet) عنوان IP.

استخدام التعليمات البرمجية التالية:

char myhostname[32];


gethostname(myhostname, 32);
hp = gethostbyname(myhostname);
unsigned my_ip = *(unsigned*)(hp->h_addr);

if( (my_ip % 256) == 127) {
  /* Wrong IP adress as it's 127.x.x.x */
  printf("Error, local IP address!");
  return;
}

السبيل الوحيد لحلها هو التأكد من بلدي المضيف في /الخ/تستضيف وراء حقيقي عنوان الشبكة, لا المحلية الاسترجاع (الافتراضي مثلاأوبونتو).

هل هناك طريقة لحل هذا دون الاعتماد على محتوى /الخ/تستضيف?

تحرير: لقد غيرت رمز أعلاه لذا فإنه يجعل من استخدام getaddrinfo, ولكن أنا لا يزال الحصول على العودة الاسترجاع الجهاز رقم (127.0,0,1) بدلا من عنوان IP الحقيقي:

struct addrinfo hint = {0};
struct addrinfo *aip = NULL;
unsigned ip = 0;
struct sockaddr_in *sinp = NULL;

hint.ai_family = AF_INET; /* IPv4 */
hint.ai_socktype = SOCK_STREAM;

if(getaddrinfo(hostname, NULL, &hint, &aip) != 0) {
    return 0;
}
sinp = (struct sockaddr_in *) aip->ai_addr;
ip   = *(unsigned *) &sinp->sin_addr;

(اعتدت أن أعود قائمة من 3 addrinfo مع ثلاثة SOCK_STREAM ، SOCK_DGRAM و SOCK_RAW ، ولكن التلميح يمنع ذلك)

لذا سؤالي لا يزال قائما...

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

المحلول

هناك POSIX وظيفة getaddrinfo() أن العوائد المرتبطة قائمة عناوين معينة المضيف ، لذلك أنت فقط تحتاج إلى الذهاب من خلال هذه القائمة تجد غير عنوان الاسترجاع.

انظر man getaddrinfo.

نصائح أخرى

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

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

بالطبع, هذا قد يكون غير ذي صلة تماما إلى التطبيق الخاص بك, ولكن اعتقد انها تجدر الإشارة إليه في هذا السياق.

التي سيتم تضمينها في الحزمة المرسلة...ليس هناك حاجة لتكرار هذه المعلومات.إنه تم الحصول عليها عند قبول البلاغ من المضيف البعيد (انظر beej دليل الشبكات ، وتحديدا الجزء المتعلق قبول())

ركضت فقط في الحالة التي تكون فيها عند فقط /الخ/تستضيف لديه معلومات في ذلك عندما كنت getaddrinfo الحصول على عنوان IP القائمة ، فإنه عاد 127.0.0.1 في كل مرة.كما اتضح أن اسم المضيف كان مستعارة إلى localhost شيء في كثير من الأحيان من السهل أن نغفل.هذا ما حدث:

/Etc/hosts الملف:
127.0.0.1 localhost.localdomain localhost فو
::1 localhost6.localdomain6 localhost6
172.16.1.248 فو
172.16.1.249 bie
172.16.1.250 bletch

هكذا, الآن, عند استدعاء getaddrinfo مع host="فو" ، فإنه يعود 127.0.0.1 3 مرات.الخطأ هنا هو أن فو يظهر سواء على الخط مع "127.0.0.1" و "172.16.1.248".بمجرد إزالة فو من خط مع "127.0.0.1" الأمور سارت على ما يرام.

نأمل أن يكون هذا يساعد شخص ما.

النظر في هذا:اكتشاف IP العام برمجيا

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

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

استخدام getaddrinfo()

أنت تقريبا هناك.لست متأكدا كيف كنت الحصول على my_ip من hp.

gethostbyname() عودة المؤشر إلى hostent هيكل الذي h_addr_list الحقل.

على h_addr_list الحقل فارغة-إنهاء قائمة من كافة عناوين ip منضم إلى أن المضيفة.

أعتقد أنك الحصول على عنوان الاسترجاع لأنه أول دخول في h_addr_list.

تحرير:يجب أن تعمل شيئا من هذا القبيل:

gethostname(myhostname, 32);
hp = gethostbyname(myhostname);
unsigned my_ip = *(unsigned*)(hp->h_addr);

for (int i = 0; hp->h_addr_list[i] != 0; ++i) {
  if (hp->h_addr_list[i] != INADDR_LOOPBACK) {
    // hp->addr_list[i] is a non-loopback address
  }
}
// no address found

إذا /etc/hosts لا يزال هناك لا يزال هو نفسه ، وتبحث عن كل الإدخالات من h_addr_list لن يساعد.

القانون الجديد الخاص بك hardwires استخدام IPv4 (في تلميح.ai_family الميدان) الذي هو فكرة سيئة.

وبصرف النظر عن هذا, أنت قريب أنت فقط يجب أن حلقة من خلال نتائج getaddrinfo.التعليمات البرمجية الخاصة بك فقط يحصل على عنوان IP الأول ولكن هناك aip->ai_next الميدانية لمتابعة...

struct addrinfo {
       ...
       struct addrinfo *ai_next;       /* next structure in linked list */
};
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top