1

パケットが途中で断片化されないように、送信者から受信者にファイルを転送しようとしています。これは、(1) 送信者から受信者へのパス上の最小 MTU の最大フラグメント化ユニット (MTU) を見つけ、(2) 次に、最小 MTU を超えないパケットでファイルを転送する 2 つのタスクで構成されます。受信ホストと送信ホストの間。

私が受信者に持っているコードは次のとおりです。

# ----    Imports     ---- # 
from socket import *
import sys, struct, time


# ----   Constants    ---- #
HOST            = ""
PORT            = 5555
ADDRESS         = (HOST,PORT)
PORT_MSGS               = 9999
TIMEOUT         = 0.0005
BUFFER                  = 65536


#---        Body        --- #
mtu = 0
numMsgs = 0

#make a socket
try:
    sckt = socket(AF_INET,SOCK_DGRAM)
    sckt.bind(ADDRESS)
    sckt.settimeout(TIMEOUT)
except socket.error:
    if sckt:
        sckt.close() # Socket Creation Failed
        sys.exit(1) # Exit program with error


#get mtu and number of messages
header = struct.pack('c','k')
while (1):  
    try:
        data, addr = sckt.recvfrom(BUFFER)
        char = struct.unpack('lc', data[0:5])[1]
        if (char == 'm'):
            mtu = struct.unpack('lc', data[0:5])[0]
            numMsgs = int(data[5:])
            #send ack for the mtu message
            sckt.sendto(header, (addr[0] ,PORT_MSGS))
            break
        if not(char == 'm'):
            continue
    except socket.error:
        continue
    except timeout:
        continue


mtuFileName = sys.argv[1]
fileName= sys.argv[2]

#make mtu file
mtuFile = open(mtuFileName,'wb')
mtuFile.write(str(mtu))
mtuFile.close()

f = open(fileName,'wb')

packetsBuffer = numMsgs * [0]
# Receive messages
packetCounter = 0
data, addr = sckt.recvfrom(BUFFER)
while (1):
        packetSeq = int(struct.unpack('lc', data[0:5])[0])
        char = struct.unpack('lc', data[0:5])[1]
        if (char == 'r') and (packetsBuffer[packetSeq] == 0):
            dataOfPack = data[5:]
            packetsBuffer[packetSeq] = dataOfPack
            packetCounter = packetCounter + 1
        if( numMsgs == packetCounter):
            break
        data, addr = sckt.recvfrom(BUFFER)


#write messages to file
buffIndex = 0
while (buffIndex < numMsgs):
    f.write(packetsBuffer[buffIndex])
    buffIndex = buffIndex + 1


f.close()
sckt.close() # close the socket

送信者は次のとおりです。

# -------    Imports    ------- #
from socket import *
import sys, struct, os, stat, commands, time


# -------   Constants    ------- #
PORT_SEND           = 5555
IP_HOST         = sys.argv[1]
SERVER_ADDRESS      = (IP_HOST  ,PORT_SEND)
MY_PORT             = 9999
MAX_FAILS_SENDING   = 10
MTU_DISCOVERY_SEQ   = 0 # the Sequence number sending MTU discovery messages
TIMEOUT             = 0.0005
BUFFER              = 65536


# -------     Body       ------- #
#socket- file
try:
    scktFile = socket(AF_INET,SOCK_DGRAM)
    scktFile.connect(SERVER_ADDRESS)
    scktFile.settimeout(TIMEOUT)
except socket.error:
    if scktFile:
        scktFile.close() # Socket Creation Failed
        sys.exit(1) # Exit program with error


#socket- ack/mtu
try:
    scktMsgs = socket(AF_INET,SOCK_DGRAM)
    scktMsgs.bind(("", MY_PORT))
    scktMsgs.settimeout(TIMEOUT)
except socket.error:
    if scktMsgs:
        scktMsgs.close() # Socket Creation Failed
        sys.exit(1) # Exit program with error


#find the mtu
mtu = int(commands.getoutput(" tracepath "+sys.argv[1]+"| grep -i resume | awk '{print $3}'"))

payloadSize = mtu-(20+8+8+5)

fileName = sys.argv[2]
f = open (fileName, 'rb') 

fileData = f.read(99999999)
fileLen = len(fileData)
numMsgs = fileLen / (payloadSize)
if((fileLen % payloadSize) != 0):
    numMsgs = numMsgs + 1


#m - mtu,k - mtu ack, a - ack, f - fin, r - regular message part of file, w - wait for ack - after  10 rounds, n -name of file
while (1):  
    header = struct.pack('lc', mtu, 'm') #m - mtu
    sNumMsgs = str(numMsgs)
    scktFile.sendto(header+sNumMsgs, SERVER_ADDRESS)
    try:
        data,addr = scktFile.recvfrom(BUFFER)
        char = struct.unpack('c', data[0])
        if char == 'k':
            break
    except socket.error:
        continue
    except timeout:
        continue


# send file content
seqNum = 0
header = struct.pack('lc', seqNum, 'r')#r - regular message part of file
while (1):
        seqNum = 0
        indexFile = 0
        header = struct.pack('lc', seqNum, 'r')
        data = fileData[indexFile:(indexFile+payloadSize)]
        indexFile = indexFile + payloadSize
        while (data):
            if(scktFile.sendto(header+data,SERVER_ADDRESS)):
                data = fileData[indexFile:(indexFile+payloadSize)]
                indexFile = indexFile+payloadSize
            #time.sleep(0.00005)
            seqNum = seqNum + 1
            seqNum = seqNum % numMsgs # Maximum Seq number
            header = struct.pack('lc', seqNum, 'r')
            if seqNum == 0:
                break


scktMsgs.close()
scktFile.close()

「0 ポイント (出力なし)」というエラーが表示され続けますが、その理由がわかりません。

4

1 に答える 1

0

これはできません。

  1. 送信パケットがパス MTU に準拠していることを確認するのは、TCP スタックの役割です。なぜあなたがアプリケーションでもその責任を負いたいと思うのかは、私には謎です.
  2. 私が認識している API では、データ転送の前に MTU を通知するものはありません。
  3. 発信パケット サイズを制御する方法はありません。TCP はバイト ストリーム プロトコルであり、パケット交換ではありません。必要に応じて、いつでも発信パケットを合体させることができます。Nagle アルゴリズムをオフにすると、これを軽減できますが、完全になくなる保証はありません。
  4. メリットはありません。TCP 経由で大量のデータを転送する最も効率的な方法は、できるだけ大きなチャンクを書き込むことであることが十分に確立されています。送信側で大きなソケット送信バッファを設定します。受信側で大きなソケット受信バッファを設定します。
于 2013-01-12T23:27:35.983 に答える