Python 如何仅在必要时从套接字读取数据
我正在与一个只有基本API支持基本API调用的硬件进行通信 不幸的是,有些API调用没有响应,有些则没有响应。我想在有回应的时候阅读,或者在没有回应的时候什么都不做 以下是我一直使用的代码:Python 如何仅在必要时从套接字读取数据,python,python-3.x,sockets,Python,Python 3.x,Sockets,我正在与一个只有基本API支持基本API调用的硬件进行通信 不幸的是,有些API调用没有响应,有些则没有响应。我想在有回应的时候阅读,或者在没有回应的时候什么都不做 以下是我一直使用的代码: def send_message(self, message, host): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((host, self.PORT)) s.sen
def send_message(self, message, host):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((host, self.PORT))
s.send(bytes(message, 'ascii'))
data = s.recv(1024)
print(data)
不幸的是,当没有收到数据时,这会绑定整个过程。我只想在有实际响应时读取数据。有没有办法用Python标准库做到这一点?我使用过类似的程序,在其中一个程序中,我使用了
if message
,message
在本例中是从套接字接收的字符串。这是我的密码:
while True:
readbuffer = readbuffer + s.recv(1024)
temp = string.split(readbuffer, "\n")
readbuffer = temp.pop()
for line in temp:
try:
user = getUser(line)
message = getMessage(line)
except IndexError:
print "Nothing to receive from the server!"
if message:
#responses here
我使用过类似的程序,在其中一个程序中,我使用了
if message
,message
,在本例中是从套接字接收的字符串。这是我的密码:
while True:
readbuffer = readbuffer + s.recv(1024)
temp = string.split(readbuffer, "\n")
readbuffer = temp.pop()
for line in temp:
try:
user = getUser(line)
message = getMessage(line)
except IndexError:
print "Nothing to receive from the server!"
if message:
#responses here
首先,如果您可以控制目标API,我建议为每条消息实现一个回复。对发送的每一条消息进行回复ACK(确认)将使您的API更加健壮,并完全避免这个问题 如果这不是一个选项,那么我将为不同类型的消息创建类:
class Message(object):
def __init__(self, msg):
self.msg = msg
class MessageWReply(Message):
await_reply = True
class MessageNoReply(Message):
await_reply = False
创建所有消息类,然后按如下方式使用它们:
def send_message(self, message, host):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((host, self.PORT))
s.send(bytes(message, 'ascii'))
if message.await_reply:
data = s.recv(1024)
print(data)
或者,如果您不想增加创建所有类的开销,可以使用字典将消息映射到正确的操作:
messages = {
'message with reply 1': True, # wait for reply
'message with reply 2': True,
'message with reply 2': True,
'message without reply 1': False, # don't wait for reply
'message without reply 2': False
}
然后这样做:
def send_message(self, message, host):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((host, self.PORT))
s.send(bytes(message, 'ascii'))
if messages[message]:
data = s.recv(1024)
print(data)
第二种方法具有更清晰的初始化(较少的样板代码),但不太清晰。对于不熟悉代码的人来说,
messages[message]
中存储的值实际上是什么意思并不清楚,而message.await\u reply
则非常清楚。类似这样的做法可能是一个很好的折衷方案—您可以在一个数据结构中初始化所有内容,同时仍然使用命名字段以保持清晰。首先,如果您可以控制目标API,我建议为每条消息实现一个回复。对发送的每一条消息进行回复ACK(确认)将使您的API更加健壮,并完全避免这个问题
如果这不是一个选项,那么我将为不同类型的消息创建类:
class Message(object):
def __init__(self, msg):
self.msg = msg
class MessageWReply(Message):
await_reply = True
class MessageNoReply(Message):
await_reply = False
创建所有消息类,然后按如下方式使用它们:
def send_message(self, message, host):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((host, self.PORT))
s.send(bytes(message, 'ascii'))
if message.await_reply:
data = s.recv(1024)
print(data)
或者,如果您不想增加创建所有类的开销,可以使用字典将消息映射到正确的操作:
messages = {
'message with reply 1': True, # wait for reply
'message with reply 2': True,
'message with reply 2': True,
'message without reply 1': False, # don't wait for reply
'message without reply 2': False
}
然后这样做:
def send_message(self, message, host):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((host, self.PORT))
s.send(bytes(message, 'ascii'))
if messages[message]:
data = s.recv(1024)
print(data)
第二种方法具有更清晰的初始化(较少的样板代码),但不太清晰。对于不熟悉代码的人来说,
messages[message]
中存储的值实际上是什么意思并不清楚,而message.await\u reply
则非常清楚。类似这样的做法可能是一个很好的折衷方案-您可以在一个数据结构中初始化所有内容,同时仍然使用命名字段以保持清晰性。如果您不知道响应是否应该遵循发送消息的先决条件,那么您就注定要失败。让我重复一遍:如果API要么响应要么不响应,而你不知道什么时候,那么游戏就结束了。这是因为“我应该等待答复吗?”这个问题无法回答。而且它与Python完全无关,切换语言无助于解决这个问题。但这样的API将非常糟糕。许多有用的工具(例如超时、并发访问)不可能(或极难)实现
另一方面,如果您确实知道API什么时候应该响应,什么时候不响应,那么只需创建两个函数即可:一个带
recv
,另一个不带。并适当地使用它们。因此,您需要做的主要工作是区分通知(不需要响应)和请求(需要响应)。就是这样。如果你不知道响应是否应该遵循发送消息的先验条件,那么你就注定要失败。让我重复一遍:如果API要么响应要么不响应,而你不知道什么时候,那么游戏就结束了。这是因为“我应该等待答复吗?”这个问题无法回答。而且它与Python完全无关,切换语言无助于解决这个问题。但这样的API将非常糟糕。许多有用的工具(例如超时、并发访问)不可能(或极难)实现
另一方面,如果您确实知道API什么时候应该响应,什么时候不响应,那么只需创建两个函数即可:一个带
recv
,另一个不带。并适当地使用它们。因此,您需要做的主要工作是区分通知(不需要响应)和请求(需要响应)。就是这样。可能取决于您的操作系统,但可能select
模块适合您?可能取决于您的操作系统,但可能select
模块适合您?