لماذا يعمل الجبيرة من sockaddr_in إلى sockaddr

3

في C طريقة نموذجية ل bind يكون مأخذ التوصيل على النحو التالي:

int server_socket_fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
int port_number = 55555;

addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(port_number);

int result = bind(server_socket_fd,(struct sockaddr *)&addr , sizeof(addr));
if(bind_result > 0)
{
    //
}

أتساءل لماذا يلقي من sockaddr_in إلى sockaddr يعمل حيث لا يمكنني العثور على أي وثائق لماذا يعمل. يبدو أن الجميع يفعل ذلك.

لماذا يعمل التلبيس هنا؟

أنا لا أسأل لماذا ألقيناها ، لقد تمت الإجابة على هذا هنا . أنا أسأل لماذا يعمل.

4 الاجابة

3
افضل جواب

يسمح بتحويل مؤشر هيكل إلى مؤشر هيكل مختلف والعكس. يتم تفصيل ذلك في القسم 6.3.2.3p7 من المعيار C :

A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer. When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.

هناك قيود في الفقرة أعلاه فيما يتعلق بالمحاذاة والتي تم تفصيلها بشكل أكبر في القسم 6.2.5p28:

A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.48) Similarly, pointers to qualified or unqualified versions of compatible types shall have the same representation and alignment requirements. All pointers to structure types shall have the same representation and alignment requirements as each other. All pointers to union types shall have the same representation and alignment requirements as each other. Pointers to other types need not have the same representation or alignment requirements.

من المفترض أن bind الدالة تعرف أي نوع من واصف مأخذ التوصيل لديها وتحول struct sockaddr * العودة إلى struct sockaddr_in * .

:مؤلف
3
افضل جواب

ال sockaddr يحتوي موقع البنية بشكل أساسي على حقل واحد فقط هو مجموعة العناوين. يمكن أن يستخدم الرمز الذي يتلقى هذا الهيكل هذا الحقل لتحديد ما هو النوع الفعلي للبنية. جميع الهياكل المستخدمة حقًا لها أيضًا هذا الحقل باعتباره الحقل الأول ، وبالتالي فإن القيمة حتمية.

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

على سبيل المثال ، تحدد Microsoft الملف sockaddr هيكل في Visual Studio 2017 كـ

struct sockaddr {  
    unsigned short sa_family;  
    char sa_data[14];  
};

sa_data
Maximum size of all the different socket address structures.

لذا يجب أن يحتوي أي هيكل "تابع" يمكن إرساله على 14 بايت من البيانات ، لا أكثر أو أقل.

بينما sockaddr_in يكون

struct sockaddr_in{  
    short sin_family;  
    unsigned short sin_port;  
struct in_addr sin_addr;  
    char sin_zero[8];  
};

هنا الميناء و in_addr تتطلب ستة بايتات في المجموع بحيث يتم استخدام 8 بايت من الحشو للحفاظ على الحجم كما هو sockaddr .

بالطبع سيكون من الممكن إنشاء على سبيل المثال sockaddr_un ، قم بتعيين عائلة عنوانها لتدعي أنها sockaddr_in وأي رمز يستقبل الهيكل سيجعلها خاطئة وستحصل على قيم خاطئة تمامًا.

:مؤلف
2
افضل جواب

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

  1. يكتب الرمز تلك الحقول عبر وسائل أخرى غير المؤشر المشتق.

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

  3. يدخل الرمز حلقة حيث سيحدث أحد ما سبق.

  4. يستدعي الرمز وظيفة حيث سيحدث واحد مما سبق.

من وجهة نظر المعيار ، فإن دعم التركيبات مثل ما سبق هو في الأساس مسألة تتعلق بجودة التنفيذ. يعترف الأساس المنطقي صراحة بإمكانية أن يكون التنفيذ "المطابق" من نوعية رديئة بحيث يكون عديم الفائدة. يجب النظر إلى أي بدل للمترجمين البدائيين للغاية للتعامل مع الحالات البسيطة مثل تلك الموضحة أعلاه (مثل gcc و clang) في هذا الضوء.

:مؤلف
1
افضل جواب

يعمل لأنه bind تستخدم الدالة فقط بعض الحقول الأولى التي يبدو أنها متشابهة في جميع عناصر sockrt_addr هيكل العائلة.

:مؤلف

أسئلة ذات صلة

فوق
قائمة طعام