我已因被搁置而修改了我的问题。希望这将更好地符合SO标准。

该程序的目的是建立和发送UDP数据包,该数据包使用“交替比特协议(protocol)”作为一种简单的重发机制。我已经确认可以正确发送和接收数据包。问题在于ABP位及其翻转。

现在我面临的问题是,尽管尝试了多种不同的方法,但我无法翻转用于确认接收到的数据包或ack是正确编号的ABP位。首先,我发送一个ABP位= 0的数据包,作为响应,接收过程应看到此情况,并发回一个ABP位= 0的确认信号。收到该消息后,发送方程序会将其ABP位翻转为1,并发送一个具有此ABP位值的新数据包。接收器将得到该信息,并发送一个ABP位= 1的匹配ack,发送器将接收,将其位翻转回0,并继续循环直到程序完成信息发送为止。

下面的代码,很抱歉,长度很长,但是它已经完整并且可以运行了。该程序带有四个命令行参数,这是我一直在使用的命令:

% python ftpc.py 164.107.112.71 4000 8000 manygettysburgs.txt

其中ftpc.py是发送方程序的名称,164.107.112.71是IP地址,4000和8000是端口号,manygettysburgs.txt是我一直在发送的文本文件。如果使用其他.txt文件,则不会有任何区别,但为完全准确起见,请使用长度在8000到9000个字符之间的文件。
import sys
import socket
import struct
import os
import select

def flipBit(val):   #flip ABP bit from 0 to 1 and vice versa
    foo = 1 - val
    return foo

def buildPacketHeader(IP, Port, Flag, ABP):
    #pack IP for transport

    #split into four 1-byte values
    SplitIP = IP.split('.')

    #create a 4-byte struct to pack IP, and pack it in remoteIP
    GB = struct.Struct("4B")

    remoteIP = GB.pack(int(SplitIP[0]),int(SplitIP[1]),int(SplitIP[2]),int(SplitIP[3]))
    #remoteIP is now a 4-byte string of packed IP values

    #pack Port for transport

    #create a 2-byte struct to pack port, and pack it in remotePort
    GBC = struct.Struct("H")

    remotePort = GBC.pack(int(Port))    #needs another byte
    #remotePort is now a 2-byte string

    #add flag
    flag = bytearray(1)
    flag = str(Flag)

    #add ABP
    ABP = flipBit(ABP)
    abp = str(ABP)

    #create header and join the four parts together

    Header = ''.join(remoteIP)
    Header += remotePort
    Header += flag
    Header += abp

    return Header


#assign arguments to local values

IP = sys.argv[1]
PORT = sys.argv[2]
TPORT = sys.argv[3]
localfile = sys.argv[4]

#declare the socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

#create destination information arrays
remoteIP = bytearray(4)
remotePort = bytearray(2)

#create flag array
flag = bytearray(1)

#create ABP bit
bit = 1
print bit

#send file size packet

#get size of file from os command
filesize = bytearray(4)
#save as 4-byte string
filesize = str(os.stat(localfile).st_size)

#package the filesize string
filesizestr = buildPacketHeader(IP,PORT,1,bit)  #build header
print bit
filesizestr += filesize                             #complete the packet
s.sendto(filesizestr, ('127.0.0.1', int(TPORT)))    #send packet

# end of send file name packet


#begin listening for responses
read, write, err = select.select([s], [], [], 1)    #timeout set to 1 seconds

if len(read) > 0:
    #data received
    data = read[0].recv(1200)
    if data[7] != bit:
        print "failed ack"
        #resend packet
else:
    print "Timeout."
    #resend packet

#send next data packet

#get filename as string (from arg4 diredtly)
filename = bytearray(20)
#save as 20-byte string
filename = localfile

#package the filename string
filenamestr = buildPacketHeader(IP,PORT,2,bit)  #build header
print bit
filenamestr += filename                             #complete the packet
s.sendto(filenamestr, ('127.0.0.1', int(TPORT)))    #send packet

#end of send file name packet


#send file content packet

#reading while loop goes here

with open(localfile, 'rb', 0) as f: #open the file
    while True:
        fstr = f.read(1000)
        if not fstr:
            print "NOTHING"
            break

        #put together the main packet base
        filecontentstr = buildPacketHeader(IP,PORT,3,bit)
        print bit

        filecontentbytearray = bytearray(1000)  #create ytear array
        filecontentbytearray = fstr             #assign fstr to byte array

        filecontentsend = ''.join(filecontentstr)   #copy filecontentstr to new string since we will be using filecontentstr again in the future for other packets

        filecontentsend += filecontentbytearray #append read data to be sent

        s.sendto(filecontentsend, ('127.0.0.1', int(TPORT)))    #send the file content packet

#end of send file content packet
s.close()

在此代码中,每次调用buildPacketHeader时,它将执行flipBit作为其操作的一部分。 flipBit应该翻转ABP的位的值。我已经设置了打印,以便在对buildPacketHeader的所有调用之后打印出bit的新值,以便跟踪该值。但是,无论何时运行程序,我总是会看到相同的ABP位值。

我尝试了几种方法,包括更改为bool。这是我尝试过的flipBit的一些更改:
def flipBit(val):   #flip ABP bit from 0 to 1 and vice versa
    if val == 0:
        val = 1
    else:
        val = 0

    return val

而有些则用bool代替:
def flipBit(val):
    val = not val
    return val

def flipBit(val):
    val = (True, False)[val]
    return val

我认为,由于过去的经验,这些方法中的许多实际上是可行的选择。就是说,我完全困惑为什么它不能按计划运行。我认为这是我对python的经验不足,因为尽管现在已经使用了相当长的时间,但仍然有一些特殊之处让我逃脱了。任何帮助是极大的赞赏。

最佳答案

我不理解您对Python int的反对,但是ctypes模块提供了一个低级可变对象的世界。例如。,

>>> import ctypes
>>> i = ctypes.c_ushort(12)  # 2-byte unsigned integer, initial value 12
>>> i
c_ushort(12)
>>> i.value += 0xffff - 12
>>> hex(i.value)
'0xffff'
>>> i.value += 1
>>> i.value  # silently overflowed to 0
0

10-04 21:46