سؤال

أقوم بإنشاء خادم FTP بلغة C.من جانب العميل أستخدم FileZilla.يحتوي الكود الخاص بي حتى الآن على جزء المصافحة فقط.

المشكلة التي أواجهها هي أن السلاسل التي أطبعها للمحطة يتم إرسالها إلى FileZilla.سؤالي هو كيف يمكنني الفصل بين هذين الأمرين، لقد جربت شيئين، لكن لم يعط أي منهما النتيجة الصحيحة.

هذا ليس سوى جزء من الكود الخاص بي، ولكن بالنسبة لسؤالي هل هذا هو الجزء المفيد:

while (FOREVER){
    addr_size = sizeof their_addr;

    newfd = accept(listener, (struct sockaddr*) &their_addr, &addr_size);
    if (newfd == -1){
        perror("accept");
        continue;
    }
    if ((send(newfd, "220 JEDI FTP is ready", 50, 0)) <= 0)
        perror("error sending");

    puts("connection established");
    puts("waiting for user & connection");
  while (!login){
        // username
        if (!user){
            if ((recv(newfd, buffer, BUFFCON, 0)) <= 0){
                puts("error receiving username");

            }
            else{

                if (strstr(buffer, "USER") != NULL){

                    if (strstr(buffer, name) != NULL){

                        send(newfd, "331 password required", 50, 0);
                        puts("username correct");

                        user = 1;
                    }
                    else{
                        puts("username incorrect");
                        send(newfd, "430 username incorrect", 50, 0);
                    }//else
                }//if
            }//else
        }//if user

وهذا هو الإخراج في FileZilla:

  • حالة:يتم إرسال عنوان المضيف المحلي
  • حالة:التقى فيربيندن [::1]:21...
  • حالة:Verbinding aangemaakt، welkomstbericht afwachten...
  • الرد:220 JEDI FTP جاهز
  • كوماندوز:المستخدم يودا
  • الرد:تم إنشاء الاتصال
  • فوت:لا يمكن أن يتم التعامل مع الخادم

لذلك بدلاً من إرسال "331 كلمة المرور مطلوبة"، يرسل "تم إنشاء الاتصال"

آمل أن تتمكن من مساعدتي في هذا، شكرا جزيلا.

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

المحلول

المشكلة هي أن الخاص بك len المعلمة ل send كبير جدا. send ليس لديه مفهوم السلاسل المنتهية بقيمة خالية؛إنه يعمل فقط مع تسلسلات البايت الأولية.لذلك المكالمة send(newfd, "220 JEDI FTP is ready", 50, 0) يرسل السلسلة "220 JEDI FTP is ready", ، ثم يأتي ما يحدث في الذاكرة بعد ذلك.من الناحية الفنية، وهذا هو سلوك غير محدد, ، حرفيا أي شئ يمكن أن يحدث (عادة ما يكون segfault).في حالتك، نظرًا لأنه عادةً ما يتم تخزين السلاسل الحرفية الثابتة بشكل تسلسلي في الذاكرة، send يقرأ السلسلة المعطاة، ثم يقرأ سلسلة مختلفة بعدها.

ما تريد القيام به هو فقط أرسل السلسلة الدقيقة (والتي، بالمناسبة، تحتاج إلى تسلسل CR-LF \r\n بعد كل أمر).لا أكثر ولا أقل.يمكنك تنفيذ أ sends وظيفة لإرسال سلسلة مثل ذلك:

ssize_t sends(int fd, const char *str)
{
    size_t len = strlen(str);
    return send(fd, str, len, 0);
}

لاحظ أيضًا أن البيانات المرسلة لا لا تضمين الإنهاء الفارغ، لأن حزمة TCP تحدد حجم السلسلة.

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