【问题标题】:Saving input fragments into a list by index and merging them通过索引将输入片段保存到列表中并合并它们
【发布时间】:2016-10-30 07:09:53
【问题描述】:

我正在使用自己的标头通过 UDP 从一台 PC 向另一台 PC 发送消息。用户可以为消息设置片段的大小,这意味着我必须将消息分成片段并将它们发送到其他 PC,我的代码应该工作什么(没有测试,因为接收是问题)。

现在,在接收方,我需要跟踪片段索引、总片段数和在我的标头中定义的其他一些内容,以检查可能的数据丢失,例如 (CRC)。但让我们回到问题上来。

我将每个收到的片段按其索引保存到list 中。所以假设标题中第一个片段的index1,所以我想将第一个片段保存在位置1。我在一段时间内一直这样做,直到我得到最后一个数据片段。但是有些东西不能正常工作。最后,我想按保存在列表中的顺序打印收到的消息,从index 1 直到使用''.join(list) 结束。

检查我的代码,它要么打印出分成片段的消息,要么当我移出while 循环的print 时,它什么也不打印,甚至没有打印Receive: 消息。

发送:

def send_loop(self):
    global mType, fragSize, fragIndex, fragCount, crc
    mType=0
    fragSize=0
    fragIndex=0 
    fragCount=0 
    crc=0
    fragSize = int(input('Fragment size: ')) #max size of fragment
while True:
            message = input('Enter message: ')
    #sending text message
            if (message[:2] == '-m'):
                mType = 1 #text message
                if message.startswith('-m '):
                    message = message[3:] # remove "-m "
                fragCount = math.ceil(len(message) / fragSize)  #rounding up number of fragments to send

                while message!= '':
                    data = bytearray()
                    data.extend(message[:fragSize].encode('utf-8'))
                    fragIndex += 1
                    header = struct.pack('!hIIII', mType, fragSize, fragIndex, fragCount, crc)
                    self.sock.sendto(header + bytearray(data), (self.host, self.port))
                    message = message[fragSize:] #set start of message to the right by size of fragSize

接收:

def create_socket(self):
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        sock.bind((self.host, self.port))
        rec_list = []
        while True:
            data, addr = sock.recvfrom(65535)
            header = data[:18]
            data = data[18:]
            (mType, fragSize, fragIndex, fragCount, crc) = struct.unpack('!hIIII', header)

        #type of message is text
            if mType == 1:
                if len(rec_list) < fragCount:
                    rec_list = ['None'] * fragCount   #empty list for messages of size fragCount
                rec_list[fragIndex] = data.decode('utf-8') 


                print(
                    '\nTyp: '       + str(mType) + 
                    '\nFragSize: '  + str(fragSize) + 
                    '\nFragIndex: ' + str(fragIndex) + 
                    '\nFragCount: ' + str(fragCount) + 
                    '\nCRC: '       + str(crc)
                    )
                msg = ''.join(rec_list)
                print('\nReceived: ' +  msg) 

【问题讨论】:

  • 我们还需要查看发送代码。
  • @JohnGordon 更新
  • while True 可以让您的套接字保持侦听,但是,您需要知道何时完成接收数据,对吧? 似乎在某处缺少某个条件(或另一个嵌套的while 循环)?另外,请记住,当您执行 rec_list = ['None'] * fragCount 时,您正在破坏您可能已经从之前的包中提取到 rec_list 中的任何信息,对吧?
  • @BorrajaX 我会看看while True,因为现在我觉得还可以,但是关于rec_list = ['None'] ,是的,我知道它会破坏以前的信息,我也需要修复它,因为我可以一个接一个地发送一条消息,它会不断重写list,但我还没有弄清楚我应该怎么做。非常感谢帮助。

标签: python list sockets udp


【解决方案1】:

所以... 下面你会发现一些代码会一直监听(在第一个 while True 中)。我添加的是第二个while 循环。当你收到一些东西时,你需要进入“重建”模式(进入第二个循环)并继续在那里,直到收到符合你的消息的所有块。

由于在每个包中都发送了您需要重建完整消息的总块数,因此您可以使用该信息来了解重建消息需要多少块。每次您收到一个包裹,这意味着您收到了一个块(并且该信息保存在received_chunks 变量中)。

一旦你收到了与总块数相同的块数,你就知道你已经重建了你的消息,你可以退出内部while继续收听下一条消息。

请注意,如果rec_list 小于符合消息的片段总数,我也会扩展。你可能不需要那个,因为在进入内部循环之前它被初始化为一个空列表。在内部循环中,您可以替换为:

if len(rec_list) < fragCount:
    need_to_add = fragCount - len(rec_list)
    rec_list.extend([None] * need_to_add)

通过这个:

if not rec_list:
    rec_list = [None] * fragCount

我这样做是为了避免过多地偏离代码。你可以做更多的清理工作。我建议做更多print(s 来查看不同变量的状态以及正在发生的事情...

while True:
    received_chunks = 0
    rec_list = []
    # Let's start receiving chunks...
    while True:
        data, addr = sock.recvfrom(65535)
        header = data[:18]
        data = data[18:]
        (mType, fragSize, fragIndex, fragCount, crc) = struct.unpack('!hIIII', header)
        print(
            '\nTyp: ' + str(mType) +
            '\nFragSize: ' + str(fragSize) +
            '\nFragIndex: ' + str(fragIndex) +
            '\nFragCount: ' + str(fragCount) +
            '\nCRC: ' + str(crc)
        )
        # type of message is text
        if mType == 1:
            if len(rec_list) < fragCount:
                need_to_add = fragCount - len(rec_list)
                rec_list.extend([None] * need_to_add)  # empty list for messages of size fragCount
            rec_list[fragIndex - 1] = data.decode('utf-8')
        print("We have received %s chunks. We expect a total of %s."
              " We are awaiting for %s chunks"
              % (received_chunks, fragCount, fragCount - received_chunks))
        received_chunks += 1
        if received_chunks == fragCount:
            break  # Get out of the second loop because we have all the chunks that we need.

        print("rec_list so far=%s" % (rec_list))
    # This is where the second (inner) while loop ends.

    print("Yay!! We got a FULL message...")
    msg = ''.join(rec_list)
    print('\nReceived: ' + msg)

【讨论】:

  • 我试过了,但是当我发送第一条消息时,它一起打印出来很好,但是当我在第一条消息之后写第二条消息时,我收到错误rec_list[fragIndex-1] = data.decode('utf-8') IndexError: list assignment index out of range
  • 哦!您的发件人脚本正在接受 python sender_script.py -m foo -m bar" 之类的东西?
  • 如果是这种情况,我认为你的问题出在sender_script...当你在其中执行message = message[3:] 时,message 将是foo -m bar ?
  • 不,不。 message=message[3:] 正在削减-m,因此消息的长度变为干净的消息,紧随在-m 之后
  • 工作!就像你说的,把它放在enter message 之后有帮助!非常感谢!
猜你喜欢
  • 2021-10-27
  • 2013-03-31
  • 1970-01-01
  • 1970-01-01
  • 2011-12-20
  • 2021-01-19
  • 1970-01-01
  • 2011-10-15
  • 2017-12-31
相关资源
最近更新 更多