0

我得到了一些代码来接收如下所示的数据:(正在使用 SSL)

sockListToCheck = self.getSocketList(self.clientSocketsWTTL)
        socksReady, w, e = select.select(sockListToCheck,[],[], d_consts.SELECT_SEC)

        if not socksReady: #list empty
            print 'not ready'
            return #nothing received yet so don't change anything

        leftInError = False
        #we have something
        for sock in socksReady:
            dataBuf = ""
            c1 = 5
            c2 = 5
            while True:
                try:
                    dat = sock.recv(d_consts.BUF_SIZE) # read what is there to read
                    dataBuf += dat
                    print(dat), len(dat)
                    if len(dat) < d_consts.BUF_SIZE and c1 == 0:
                        c1 -= 1
                        print 'about to break'
                        break
                except ssl.SSLError as e:
                    #print 'trying to read '
                    # Ignore the SSL equivalent of EWOULDBLOCK, but re-raise other errors
                    #print e
                    if e.errno != ssl.SSL_ERROR_WANT_READ:
                        print 'serious ssl error'
                        sock.shutdown(socket.SHUT_RDWR)
                        sock.close() #close
                        leftInError = True
                    else: 
                        if c2 == 0:
                            break
                        c2 -= 1
                        continue

            if (leftInError):
                leftInError = False
                print 'left error'
                continue

当有一些明显的延迟时我遇到了问题,所以我添加了这些计数器。我的问题是,如果我不知道消息有多大,我不知道何时停止接收。当接收到的数量小于缓冲区时,我曾经中断过,但似乎有时会发生这种情况,但并非所有数据都已到达。还有其他方法吗?也许有些超时或什么?

4

2 回答 2

1

这是网络编程的普遍问题。答案是在大多数情况下你不应该使用原始套接字。

通常我会建议切换到ØMQ,因为它是一个很棒的库,它可以让你根据消息而不是 TCP 的字节流来工作。这就是你大部分时间真正需要的。

但不幸的是,ØMQ目前不能很好地与 SSL 配合使用。因此,您自然有两种选择:

  1. 编写大量样板代码。您将需要一个有线协议(至少带有“消息长度”字段)和代码,这些代码将仔细地从套接字读取字节并计算它们。
  2. 使用一些现有的库。我首先想到的是使用消息代理,例如支持SSL的RabbitMQ
  3. 一个更激进的解决方案(但我认为最棒的一个)是完全摆脱 TCP 并转向更强大的协议,例如SCTP。你可能不应该选择这个选项……</li>

如果你选择第一个选项。

首先,在发送消息之前,以某种固定长度格式(例如 4 字节无符号整数)发送它的长度。现在:

  1. 创建一个缓冲区(字节列表)。
  2. 继续从套接字读取并附加到这个缓冲区,直到你有 4 个字节。
  3. 当缓冲区的长度至少为 4 时,删除前四个字节,并保留其余字节:

    if len(buffer) >= 4:
        expected_length = int(buffer[:4])
        buffer = buffer[4:]
    
  4. 现在您继续将字节接收到缓冲区中,直到其长度变为expected_length.
  5. len(buffer) >= expected_length你收到消息时。

Python Sockets HOWTO中显示了类似的内容,但它们假定消息长度固定。

于 2013-06-08T09:51:11.510 回答
-1

很难确切地说出您的代码有什么问题,因为它不完整(例如,创建套接字的代码丢失了,所以我无法判断它们是阻塞套接字还是非阻塞套接字,甚至是两者的混合)。我也无法运行代码并探索不当行为,这对解决此类问题有很大帮助。

但是,我建议改用 Twisted 的 SSL 支持。它将为您完成所有这些无聊的低级工作,并让您专注于您的实际应用程序。

在最糟糕的情况下,您可以阅读Twisted 的 SSL 实现(或旧版本)来了解您需要解决的各种极端情况,以便能够一起使用 SSL 和选择。

于 2013-06-08T11:51:26.433 回答