我使用asyncio实现了一个TCP服务器,它以固定的间隔从客户端接收数据,比如每30秒一次。现在,我的目标是按需向客户端发送数据。为了实现这一点,我打算建立一种机制,在其中可以在客户端设置特定的参数。因此,我需要为此目的从服务器向客户端发送消息。
我曾尝试实施这一点,但它是行不通的
这是我的代码
import asyncio
from protocol import Message # Import your Message class from protocol.py
class TCPServer:
def __init__(self, host, port):
self.host = host
self.port = port
self.server = None
self.clients = {} # Dictionary to store connected clients
self.input_queue = asyncio.Queue() # Queue for console input
async def handle_client(self, reader, writer):
message = Message() # Create an instance of your Message class
addr = writer.get_extra_info('peername')
# Convert the client address to a string for consistency
client_address = f"{addr[0]}:{addr[1]}"
try:
self.clients[client_address] = writer # Store the writer for this client
while True:
data = await reader.read(1024)
if not data:
break
# Assuming your Message class has a `raw_data` method
response = message.raw_data(data)
print(f"Received {data!r} from {addr!r}")
print(f"Send: {response!r}")
writer.write(response.encode())
await writer.drain()
except ConnectionResetError as e:
print(f"ConnectionResetError: {e}")
except Exception as e:
print(f"Error: {e}")
finally:
print(f"Client {addr!r} closed the connection")
writer.close()
await writer.wait_closed()
del self.clients[client_address] # Remove the client from the list when they
disconnect
async def send_to_client(self, client_address, message):
if client_address in self.clients:
writer = self.clients[client_address]
writer.write(message.encode())
await writer.drain()
else:
print("Client not found or not connected.")
async def start(self):
self.server = await asyncio.start_server(
self.handle_client, self.host, self.port)
addr = self.server.sockets[0].getsockname()
print(f'Serving on {addr}')
async with self.server:
await self.server.serve_forever()
async def stop(self):
if self.server:
self.server.close()
await self.server.wait_closed()
print("Server stopped")
async def console_input(self):
while True:
client_address = await self.input_queue.get()
hex_data = input("Enter the hex data to send: ")
try:
byte_data = bytes.fromhex(hex_data)
await self.send_to_client(client_address, byte_data)
except ValueError:
print("Invalid hex data format.")
if __name__ == '__main__':
host = '127.0.0.1' # Change this to the desired host
port = 8888 # Change this to the desired port
server = TCPServer(host, port)
async def main():
try:
server_task = asyncio.create_task(server.start())
console_task = asyncio.create_task(server.console_input())
# Add client address to the input queue for testing
await asyncio.sleep(2) # Wait for the server to start (adjust as needed)
client_address = '127.0.0.1:8888'
server.input_queue.put_nowait(client_address)
await asyncio.gather(server_task, console_task)
except KeyboardInterrupt:
print("KeyboardInterrupt: Server shutting down...")
await server.stop()
asyncio.run(main())
1条答案
按热度按时间6rqinv9w1#
看起来你想在Python中使用asyncio实现一个TCP服务器,它可以定期从客户端接收数据,并按需向客户端发送数据。但是,你提到发送部分不工作。为了帮助您解决这个问题,我将为您的代码提供一些指导和潜在的修复:
确保正确的消息处理:
在send_to_client方法中,使用writer.write(message.encode())向客户端发送数据。但是,您需要考虑客户端期望如何接收和处理此数据。确保客户端知道如何解析和处理服务器发送的消息。正确处理队列任务:
在main函数中,为server.start()和server.console_input()创建任务。但是,您应该使用awaitasyncio.gather(...)等待这些任务,以确保它们并发运行。下面是代码的修改版本,其中包含以下更改:
请注意,我已经删除了向客户端发送消息时的.encode()方法,假设您的消息已经是字节格式。确保客户端也需要相同格式的数据。此外,请确保正确实现了protocol.py文件,以处理服务器发送的消息。