Реализуйте взаимодействие сервера и клиента через сокеты на Python. ⇐ Python

Программы на Python
Anonymous
Реализуйте взаимодействие сервера и клиента через сокеты на Python.

Сообщение Anonymous »

Мне нужно реализовать взаимодействие сервера и клиента через сокеты на Python. Я решил реализовать сервер с помощью asyncio.start_server. Клиенты подключаются к серверу через сокетные соединения. Сервер генерирует несколько сообщений в случайные моменты и немедленно отправляет эти сообщения клиенту. Все клиенты должны как можно скорее получать одни и те же сообщения и распечатывать их.
Моя реализация сервера:

Код: Выделить всё

import asyncio
import datetime as dt
import struct
import sys

from random import randrange
from zoneinfo import ZoneInfo

async def prepare_weather_data():
while True:
await asyncio.sleep(randrange(0, 7))

now = dt.datetime.now(ZoneInfo("Europe/Kyiv")).replace(microsecond=0).isoformat()
massage = f"{now} The temperature is {str(randrange(20, 30))} degrees Celsius"

message_encoded = massage.encode()
message_length = struct.pack('>I', len(message_encoded))

yield message_length + message_encoded

async def read_massage(reader: asyncio.StreamReader):
# Read the 4-byte length header
length_data = await reader.readexactly(4)
message_length = struct.unpack('>I', length_data)[0]
message_encoded = await reader.readexactly(message_length)
return message_encoded.decode()

async def handle_client(
_: asyncio.StreamReader,
writer: asyncio.StreamWriter,
weather_data: bytes,
):
try:
writer.write(weather_data)
await writer.drain()
except KeyboardInterrupt:
print("Closing the connection")
writer.close()
sys.exit(0)

async def main():
async def client_handler(reader, writer):
message = await read_massage(reader)
print(f"Received the message \"{message}\" that won't be handled any way")

async for weather_data in prepare_weather_data():
await handle_client(reader, writer, weather_data)

server = await asyncio.start_server(client_handler, "localhost", 8000)
async with server:
await server.serve_forever()

if __name__ == "__main__":
asyncio.run(main())
Клиент:

Код: Выделить всё

import sys
import socket
import struct

def recvall(sock: socket.socket, n: int) -> bytes | None:
# Helper function to recv n bytes or return None if EOF is hit
data = bytearray()
while len(data) < n:
packet = sock.recv(n - len(data))
if not packet:
return None
data.extend(packet)
return data

def read_massage(sock: socket.socket) -> str | None:
# Read the 4-byte length
message_length_encoded = recvall(sock, 4)
if not message_length_encoded:
print("Socket closed")
sys.exit(0)

message_length = struct.unpack('>I', message_length_encoded)[0]
return recvall(sock, message_length).decode()

so = socket.socket(
socket.AF_INET,
socket.SOCK_STREAM,
)

so.connect(("localhost", 8000))  # Blocking
print("Connected")

try:
message = "Hello, give me a weather, please".encode()

# Pack the length of the message into 4 bytes (big-endian)
message_length = struct.pack('>I', len(message))
sent = so.send(message_length + message)  # Blocking
print(f"Sent {sent} bytes")

while True:
msg = read_massage(so)
print(msg)

except KeyboardInterrupt:
so.close()
print("Socket closed")
sys.exit(0)
Эта версия сервера в целом работает. Сервер генерирует сообщения и отправляет их клиентам. Однако все клиенты получают разные сообщения! Как изменить сервер, чтобы он отправлял одно и то же сообщение всем клиентам? Я попробовал все, что мог.

Подробнее здесь: https://stackoverflow.com/questions/790 ... -in-python

Вернуться в «Python»