我已因被搁置而修改了我的问题。希望这将更好地符合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