两个tcp客户端,一个读,一个写

Two tcp clients, one for reading, the other for writing

您需要为tcp 服务器编写代码。 第一个连接的客户端将只发送一些数据到服务器,所以服务器应该只读那些数据。 第二个客户端应该只读取数据,因此服务器应该只发送一些数据给这个客户端。在我的例子中,服务器应该每 3 秒向第二个客户端发送一次数据。

如何同时使用两个tcp 连接。一个接收数据,另一个发送数据?

需要在python语言中使用异步

我试过了,这是我的代码。

server.py

import asyncio
import time

import logging

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s,%(levelname)s:%(message)s',
    datefmt='%d-%m-%Y %H:%M:%S'
)

client_loop = True
first_client_addr = None
msg = 'test'

async def handle_client(reader, writer):
    global client_loop
    global first_client_addr
    global msg

    addr = writer.get_extra_info('peername')

    logging.info(f'New client {addr}')
    
    if first_client_addr == None:
        first_client_addr = addr

    if addr == first_client_addr:
        request = None
        while client_loop:
            request = (await reader.read(1024)).decode('utf8')
            msg = request
            logging.info(f'Received {request!r} from {addr!r}')

    else:
        while client_loop:
            response = msg
            writer.write(response.encode('utf8'))
            await writer.drain()
            logging.info(f'Sended {response!r} to {addr!r}')
            time.sleep(3)
    writer.close()


async def run_server():
    server = await asyncio.start_server(handle_client, '0.0.0.0', 8686)
    async with server:
        await server.serve_forever()

asyncio.run(run_server())

第一步是连接客户端发送用户数据。

然后,一旦第二个客户端连接,我就停止从第一个客户端接收任何数据,也就是说,它们根本无法读取。

我一杀死第二个客户端,服务器就开始再次从第一个客户端读取数据。服务器日志:

08-04-2022 17:19:23,INFO:New client ('127.0.0.1', 47314)
08-04-2022 17:19:23,INFO:Received 'First connection message, client 2.' from ('127.0.0.1', 47314)
08-04-2022 17:19:25,INFO:Received 'g' from ('127.0.0.1', 47314)
08-04-2022 17:19:26,INFO:Received 'a' from ('127.0.0.1', 47314)
08-04-2022 17:19:27,INFO:New client ('127.0.0.1', 47316)
08-04-2022 17:19:27,INFO:Sended 'a' to ('127.0.0.1', 47316)
08-04-2022 17:19:30,INFO:Sended 'a' to ('127.0.0.1', 47316)
08-04-2022 17:19:33,INFO:Sended 'a' to ('127.0.0.1', 47316)
08-04-2022 17:19:36,INFO:Sended 'a' to ('127.0.0.1', 47316)
08-04-2022 17:19:39,INFO:Sended 'a' to ('127.0.0.1', 47316)
08-04-2022 17:19:42,INFO:Sended 'a' to ('127.0.0.1', 47316)
08-04-2022 17:19:45,INFO:Sended 'a' to ('127.0.0.1', 47316)
08-04-2022 17:19:48,INFO:Sended 'a' to ('127.0.0.1', 47316)

怎么会这样,因为这是两个不同的客户端,不应该互相影响。 请帮我解决这个问题。解释为什么会发生这种情况或编写代码。


这是我的两个客户的代码,但并不是真正需要的。

client_send.py

import asyncio
import time

async def send_client():
    reader, writer = await asyncio.open_connection(
        '127.0.0.1', 8686
    )

    message = 'First connection message, client 2.'
    writer.write(message.encode())
    await writer.drain()
    print('First connection for client 2 done.')

    print('Start loop')
    data = None
    while data != 'quit':
        data = input()
        writer.write(data.encode())
        await writer.drain()

    print('Close the connection')
    writer.close()
    await writer.wait_closed()

asyncio.run(send_client())

client_listen.py

import asyncio

async def listen_client():
    reader, writer = await asyncio.open_connection(
        '127.0.0.1', 8686
    )

    message = 'First connection message, client 1.'
    writer.write(message.encode())
    await writer.drain()
    print('First connection for client 1 done.')

    print('Loop has been started')
    data = None
    while data != 'quit':
        response = await reader.read(1024)
        data = response.decode()
        print(f'Received: {data!r}')

    print('Close the connection')
    writer.close()
    await writer.wait_closed()

asyncio.run(listen_client())

问题是这个sleep(3)。这使整个服务器进入睡眠状态,所以它不是 receiving/sending 任何东西。在异步代码中,您需要使用 await asyncio.sleep(3).

我也稍微重构了服务器代码:

import asyncio
import logging


logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s,%(levelname)s:%(message)s",
    datefmt="%d-%m-%Y %H:%M:%S",
)

msg = "test"
clients = []


async def handle_read(reader, addr):
    global msg

    while True:
        msg = (await reader.read(1024)).decode("utf-8")
        logging.info(f"Received {msg!r} from {addr!r}")


async def handle_write(writer, addr):
    while True:
        await asyncio.sleep(3)

        writer.write(msg.encode("utf8"))
        await writer.drain()
        logging.info(f"Sended {msg!r} to {addr!r}")


async def handle_client(reader, writer):
    global num_clients

    addr = writer.get_extra_info("peername")
    logging.info(f"New client {addr}")

    if not clients:
        # first client is modifying `msg`
        clients.append(asyncio.create_task(handle_read(reader, addr)))
    else:
        # all other clients are receiving `msg` every 3 seconds
        clients.append(asyncio.create_task(handle_write(writer, addr)))

    await clients[-1]


async def run_server():
    server = await asyncio.start_server(handle_client, "0.0.0.0", 8686)
    async with server:
        await server.serve_forever()


asyncio.run(run_server())

第一个客户是特别 - 正在修改msg。所有其他客户端每 3 秒接收一次 msg 第一个客户端发送的消息。