python - 如何将 select 与 Python ssl 套接字缓冲一起使用?

标签 python sockets select ssl buffer

我的问题类似于 python - How select.select() works? 。但是,那里的解决方案对我不起作用,因为我没有打开()我的文件。相反,它是一个套接字。我找不到任何方法将其设置为无缓冲 documentation .

我有一个glib mainloop(它使用select),我在其中注册了用于读取的套接字。因为 socket.recv() 要求我指定接收缓冲区大小,所以读取的字节数少于套接字读取的字节数并不罕见。只要内核缓冲它们就可以了; select 仍会将套接字标记为“准备读取”。但显然 Python 也有一个缓冲区。对于大文件,在数据流末尾附近,recv() 将读取其中的一部分,其余部分将由 Python 缓冲,并且 select 不再在我的套接字上触发,直到发送新数据。此时,“丢失”的数据先于新数据被接收;没有数据丢失。

我的问题是:我该如何解决这个问题?有没有办法禁用Python套接字上的缓冲区?如果不是,有没有办法检查缓冲区是否为空,这样我就可以确保在缓冲区为空之前我不会从回调中返回?

编辑:

正如评论中所指出的,Python 不会向套接字添加额外的缓冲区,因此这不可能是问题。我无法为该问题创建一个最小的示例。不过,这似乎可能与使用 ssl 套接字有关。我忘记了我使用了加密连接;禁用加密似乎可以解决这个问题,但对我来说是 Not Acceptable 。所以上面的问题仍然存在,请注意缓冲区可能是在 ssl 模块中实现的。

显示问题的示例代码:

#!/usr/bin/python

import glib
import socket
import ssl

def cb (fd, cond):
    print ('data: %s' % repr (s.read (1)))
    return True

s = ssl.wrap_socket (socket.create_connection (('localhost', 1234)))
glib.io_add_watch (s.fileno (), glib.IO_IN, cb)
glib.MainLoop ().run ()

然后运行服务器

openssl s_server -accept 1234 -key file.key -cert file.crt

运行python程序将建立连接。发送超过一个字节的数据将使程序只打印第一个字节;当发送更多字节时,首先读取剩余的 block ,然后读取第一个新字节,然后再次等待。这很容易理解:只要ssl缓冲区中有数据,就不会从内核缓冲区读取新字节,因此select继续报告它。

最佳答案

查看 ssl 源代码,我发现一个未记录的函数可以执行我想要的操作:pending()。它可以像这样使用:

#!/usr/bin/python

import glib
import socket
import ssl

def cb(fd, cond):
    print('data: %s' % repr(s.read(1)))
    while(s.pending()):
        print('more data: %s' % repr(s.read(1)))
    return True

s = ssl.wrap_socket (socket.create_connection(('localhost', 1234)))
glib.io_add_watch(s.fileno(), glib.IO_IN, cb)
glib.MainLoop().run()

这解决了问题。

关于python - 如何将 select 与 Python ssl 套接字缓冲一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21663705/

相关文章:

linux - SLES 9 与 SLES 10

mysql - 选择每个玩家的最佳分数

c++ - 如何用swig实例化模板类的模板方法?

javascript - jQuery Web Socket 未连接且未发送

c - 简单客户端/服务器的问题,文件打印错误

html - 有没有办法在选择标签中选择 optgroup 的标签?

MySql SELECT AVG CASE 语句组错误

python - 根据字符位置从字符串中提取子字符串 - Python

python - Python 保持套接字事件时遇到问题

python - 如何将二维列表导出为ascii文件?