是我,还是我在python中找不到关于非阻塞套接字的好教程?
我不确定如何准确地使用.recv
和.send
。根据python文档,(我对它的理解,至少)recv
'ed或send
'ed数据可能只是部分数据。这是否意味着我必须在recv
时以某种方式连接数据,并确保所有数据都通过send
发送。如果是这样,怎么样?一个例子将非常感激。
答案 0 :(得分:8)
如果您的套接字处于非阻塞模式并不重要,recv / send工作几乎相同;唯一的区别是非阻塞套接字抛出'资源暂时不可用'错误而不是等待数据/套接字。
recv 方法返回收到的字节数,告知该字节数小于或等于传递的bufsize。如果您想要接收 size 字节,则应该执行类似于以下代码的操作:
def recvall(sock, size):
data = ''
while len(data) < size:
d = sock.recv(size - len(data))
if not d:
# Connection closed by remote host, do what best for you
return None
data += d
return data
重要的是要记住,在阻止模式下,您必须完全相同。 (传递给应用层的字节数例如受OS中recv缓冲区大小的限制。)
发送方法返回发送的字节数,这被告知要小于或等于传递的字符串的长度。如果要确保发送整个消息,则应执行与以下代码类似的操作:
def sendall(sock, data):
while data:
sent = sock.send(data)
data = data[sent:]
您可以直接使用sock.sendall,但是(根据文档)出错时会引发异常,并且无法确定成功发送了多少数据()
Python中的套接字遵循BSD套接字API,其行为方式与c风格的套接字类似(例如,不同之处在于它们抛出异常而不是返回错误代码)。您应该对Web和联机帮助页上的任何套接字教程感到满意。
答案 1 :(得分:0)
保留要在缓冲区中发送的字节。 (字节字符串列表最好,因为您不必连接它们。)使用fcntl.fcntl
函数将套接字设置为非阻塞模式:
import fcntl, os
fcntl.fcntl(mysocket, fcntl.F_SETFL, os.O_NONBLOCK)
然后select.select
将告诉您何时可以读取和写入套接字。 (写入不正常时会在非阻塞模式下出现EAGAIN
错误。)编写时,检查返回值以查看实际写入的字节数。消除缓冲区中的那么多字节。如果使用字符串列表方法,则只需尝试每次编写第一个字符串。
如果您读取空字符串,则套接字已关闭。