使用套接字传输文件并找到最大mtu

时间:2013-01-12 19:44:21

标签: python sockets

我正在尝试将文件从发送方传输到接收方,以使数据包不会在路由中分段。这包括两个任务:(1)找出从发送方到接收方的路径上的最小MTU的最大分段单元(MTU),以及(2)然后在不超过最小MTU的分组中传输文件接收和发送主机之间。

我对接收方的代码是:

# ----    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分(无输出)”,我不知道为什么

1 个答案:

答案 0 :(得分:0)

你不能这样做。

  1. TCP堆栈的责任是确保传出数据包符合路径MTU。你为什么要在应用程序中承担责任对我来说是一个谜。
  2. 我所知道的API没有告诉您任何数据传输之前的MTU。
  3. 无法控制传出的数据包大小。 TCP是一种字节流协议,而不是数据包交换,它有权在它感觉到的时候合并传出的数据包。关闭Nagle算法可以减轻这种影响,但不能保证消除它。
  4. 没有任何好处。众所周知,通过TCP传输批量数据的最有效方法是尽可能地写入大块数据;在发送方设置一个大的套接字发送缓冲区;并在接收器处设置一个大的套接字接收缓冲区。