2

Я хотел бы проверить взаимодействие между клиентской программой и серверной программой для условий гонки. Они соединяются друг с другом через TCP. Клиент блокирует вызовы к серверу в нескольких потоках (по одному tcp-соединению с сервером на поток). Я хотел бы проверить состояние гонки, когда один блокирующий вызов заканчивается раньше другого.

Для этого я надеялся задержать tcp-соединения на разные суммы (поэтому мне не нужно явно переписывать ни клиента, ни сервера).

Я надеялся сделать что-то вроде этого:

socat tcp-listen:$pin system:"delaycat $delay |socat - 'tcp:localhost:$pout'"

где $pin - это порт, к которому подключается клиент, $delay - это количество секунд для задержки, а $pout - это порт, который слушает сервер. А delaycat - это воображаемая программа, которая задерживает входной поток на n секунд.

Есть какая-нибудь существующая программа, которая делает то, что я хочу? Или я должен написать delaycat?

Изменить: обратите внимание, что общесистемная задержка не была бы идеальной, так как я хотел бы задержать отдельные сокеты на разные суммы, если это возможно.

2 ответа2

2

Я не смог ничего найти там уже, поэтому я написал для этого скрипт на python (возможно, он глючит):

#!/usr/bin/env python26
"""Add latency to a tcp connection"""
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
from functools import partial

from twisted.internet.reactor import (
    listenTCP, connectTCP, callLater, run
)
from twisted.internet.protocol import (
    ServerFactory, ReconnectingClientFactory, Protocol
)


class ConnectionToServer(Protocol):
    def __init__(self, connection_from_client, delay_to_client):
        self._delay_to_client = delay_to_client
        self._connection_from_client = connection_from_client

    def connectionMade(self):
        self._connection_from_client.connection_to_server = self
        if self._connection_from_client.buffer_from_client:
            self.transport.write(
                self._connection_from_client.buffer_from_client
            )

    def dataReceived(self, data):
        callLater(
            self._delay_to_client,
            self._connection_from_client.transport.write, data
        )

    def connectionLost(self, reason):
        callLater(
            self._delay_to_client,
            self._connection_from_client.transport.loseConnection
        )


class ConnectionFromClient(Protocol):
    def __init__(self, server_host, server_port, delay_to_client, delay_to_server):
        self._delay_to_server = delay_to_server
        self.connection_to_server = None
        self.buffer_from_client = ''
        server_connection_factory = ReconnectingClientFactory()
        server_connection_factory.protocol = partial(
            ConnectionToServer, self, delay_to_client
        )
        self._server_connector = connectTCP(
            server_host, server_port, server_connection_factory
        )

    def dataReceived(self, data):
        callLater(self._delay_to_server, self._write, data)

    def connectionLost(self, reason):
        callLater(
            self._delay_to_server, self._server_connector.disconnect
        )

    def _write(self, data):
        if self.connection_to_server:
            self.connection_to_server.transport.write(data)
        else:
            self.buffer_from_client += data


def main():
    """Add latency to a tcp connection"""
    parser = ArgumentParser(
        description=main.__doc__,
        formatter_class=ArgumentDefaultsHelpFormatter
    )
    parser.add_argument(
        'client_port', type=int, help='client connects to this port'
    )
    parser.add_argument(
        'server_port', type=int, help='server listens on this port'
    )
    parser.add_argument(
        '-t', '--server-host', default='localhost',
        help='server is running on this host'
    )
    parser.add_argument(
        '-c', '--delay-to-client', default=0, type=float,
        help='messages to client are delayed by this many seconds'
    )
    parser.add_argument(
        '-s', '--delay-to-server', default=0, type=float,
        help='messages to server are delayed by this many seconds'
    )
    args = parser.parse_args()
    client_connection_factory = ServerFactory()
    client_connection_factory.protocol = partial(
        ConnectionFromClient, args.server_host, args.server_port,
        args.delay_to_client, args.delay_to_server
    )
    listenTCP(args.client_port, client_connection_factory)
    run()
if __name__ == '__main__':
    main()
1

На Linux-машине вы можете использовать tc с Netem.

Например, команда tc qdisc add dev eth0 root netem delay 100ms задержит все исходящие пакеты на 100 миллисекунд. Для задержки входящих пакетов вы можете использовать промежуточный функциональный блок ifb

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .