这是一个消息应用程序,可以发送消息从一个客户端到另一个客户端通过服务器,我调试这段代码,它是循环的read_socket, _, _ = select.select(self。输入,[],[],1) 用于读取read_socket: for ever。
import socket
import select
import errno
import sys
class client_app():
def __init__(self):
self.HEADER_LENGTH = 10
self.IP = "127.0.0.1"
self.PORT = 1234
self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.client_socket.connect((self.IP, self.PORT))
self.client_socket.setblocking(False)
self.inputs = [sys.stdin, self.client_socket]
def client(self, send_message):
while True:
read_socket, _ , _ = select.select(self.inputs, [], [], 1)
for read in read_socket:
if read is client_socket:
try:
while True:
message_header = client_socket.recv(HEADER_LENGTH)
message_length = int(message_header.decode('utf-8').strip())
message = client_socket.recv(message_length).decode('utf-8')
print(message)
except IOError as e:
if e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK:
sys.exit()
continue
except Exception as e:
sys.exit()
else:
try:
message = send_message
if message:
message = message.encode('utf-8')
message_length = int(message_header.decode('utf-8').strip())
client_socket.send(message_header + message)
except IOError as e:
if e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK:
sys.exit()
continue
except Exception as e:
sys.exit()
if __name__=='__main__':
cli = client_app()
cli.client('ahmad')
cli.client('jan')```
问题来源StackOverflow 地址:/questions/59379805/looping-on-select-select-method-for-infinite
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
这段代码展示了一个简单的客户端应用程序,它使用Python的socket
和select
模块来实现实时地从服务器接收消息以及向服务器发送消息。下面是对代码中关键部分的解释以及可能存在的问题和改进建议:
初始化与连接:客户端通过socket.socket()
创建一个套接字,并使用connect()
方法连接到指定的IP地址和端口。这里设置为本地环回地址(127.0.0.1
)和端口1234
。
非阻塞模式:通过setblocking(False)
将套接字设置为非阻塞模式,这意味着当没有数据可读时,recv()
调用不会阻塞,而是立即返回一个错误。
使用select监控输入:select.select()
函数用于同时监控多个IO通道(如文件描述符)。在这个例子中,它监控标准输入(用户输入)和客户端套接字是否有数据可读。第四个参数1
是超时时间,意味着如果在1秒内没有I/O事件发生,select()
会返回。
消息处理循环:
message_header = client_socket.recv(HEADER_LENGTH)
应该放在外层循环里,因为它只需要在开始读取新消息时获取一次。message_length = int(message_header.decode('utf-8').strip())
这行应该是在准备发送消息之前计算消息的实际长度,而不是在这里重复使用接收时的逻辑。此外,发送消息时应确保正确构造了消息头和消息体。错误处理:通过捕获IOError
和更通用的Exception
来处理潜在的错误,比如网络中断或编码解码错误。
client('ahmad')
和client('jan')
连续调用,但实际应用中通常不需要这样。可以考虑在主循环中等待用户输入不同的消息再发送。try...finally
或上下文管理器(with
语句)确保资源被妥善释放。下面是修改后的发送消息部分示例代码:
def client(self, send_message):
message = send_message.encode('utf-8')
message_header = f"{len(message):<{self.HEADER_LENGTH}}".encode('utf-8')
while True:
read_socket, _, _ = select.select(self.inputs, [], [], 1)
for read in read_socket:
if read is self.client_socket:
try:
message_header = self.client_socket.recv(self.HEADER_LENGTH)
if not len(message_header):
print("Connection closed by the server.")
sys.exit()
message_length = int(message_header.decode('utf-8').strip())
message = self.client_socket.recv(message_length).decode('utf-8')
print(message)
except IOError as e:
if e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK:
sys.exit()
continue
except Exception as e:
sys.exit()
else:
try:
self.client_socket.send(message_header + message)
# 可能需要清除或更新send_message变量,取决于你的需求
except IOError as e:
if e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK:
sys.exit()
continue
except Exception as e:
sys.exit()
请注意,上述修改仅针对你提供的代码片段进行,具体应用中还需根据实际情况调整。