سؤال

لديّ برنامجان ، sendfile.py و recvfile.py من المفترض أن يتفاعلوا لإرسال ملف عبر الشبكة. يتواصلون على مآخذ TCP. من المفترض أن يذهب الاتصال شيئًا كهذا:

sender =====filename=====> receiver

sender <===== 'ok' ======= receiver
               or
sender <===== 'no' ======= receiver

if ok:
sender ====== file ======> receiver 

لدي

رمز المرسل ورمز المتلقي هنا:

مرسل:

import sys
from jmm_sockets import *

if len(sys.argv) != 4:
    print "Usage:", sys.argv[0], "<host> <port> <filename>"
    sys.exit(1)

s = getClientSocket(sys.argv[1], int(sys.argv[2]))

try:
    f = open(sys.argv[3])
except IOError, msg:
    print "couldn't open file"
    sys.exit(1)

# send filename
s.send(sys.argv[3])

# receive 'ok'
buffer = None
response = str()
while 1:
    buffer = s.recv(1)
    if buffer == '':
        break
    else:
        response = response + buffer
if response == 'ok':
    print 'receiver acknowledged receipt of filename'
    # send file
    s.send(f.read())
elif response == 'no':
    print "receiver doesn't want the file"

# cleanup
f.close()
s.close()

المتلقي:

from jmm_sockets import *

s = getServerSocket(None, 16001)
conn, addr = s.accept()


buffer = None
filename = str()

# receive filename
while 1:
    buffer = conn.recv(1)
    if buffer == '':
        break
    else:
        filename = filename + buffer
print "sender wants to send", filename, "is that ok?"
user_choice = raw_input("ok/no: ")

if user_choice == 'ok':
    # send ok
    conn.send('ok')
    #receive file
    data = str()
    while 1:
        buffer = conn.recv(1)
        if buffer=='':
            break
        else:
            data = data + buffer
            print data
else:
    conn.send('no')
conn.close()

أنا متأكد من أنني أفتقد شيئًا هنا في أنواع الجمود ، لكن لا أعرف ما هو عليه.

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

المحلول

TCP هو بروتوكول تدفق. ليس لديه مفهوم لحدود الرسائل. لمقبس الحظر ، RECV(ن) سيعود سلسلة طول صفر فقط عندما يغلق المرسل المقبس أو يسمى صراحة اغلق(Shot_wr). وإلا فإنه يمكن أن يعيد سلسلة من بايت واحد إلى N في الطول ، وسيحظر حتى يحصل على بايت واحد على الأقل للعودة.

الأمر متروك لك لتصميم بروتوكول لتحديد متى يكون لديك رسالة كاملة. بعض الطرق هي:

  1. استخدم رسالة ذات طول ثابت.
  2. أرسل رسالة ذات طول ثابت تشير إلى إجمالي طول الرسالة ، تليها الجزء المتغير من الرسالة.
  3. أرسل الرسالة ، تليها رسالة إنهاء فريدة لن تحدث أبدًا في الرسالة.

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

نصائح أخرى

مع حظر مآخذ ، والتي هي الافتراضي وافترض أنها ما تستخدمه (لا يمكن أن تكون متأكداً لأنك تستخدم وحدة غامضة jmm_sockets)، ال recv الطريقة التي تمنعها - لن تُرجع سلسلة فارغة عندما لا يكون هناك "لا شيء للعودة في الوقت الحالي" ، كما يبدو أنك تفترض.

يمكن أن تدور حول هذا ، على سبيل المثال ، عن طريق إرسال حرف Terminator الصريح (يجب ألا يحدث أبدًا داخل اسم الملف) ، على سبيل المثال '\xff', ، بعد السلسلة الفعلية التي تريد إرسالها ، وانتظارها في الطرف الآخر كدليل على أن جميع السلسلة قد تم استلامها الآن.

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