Wie verzögere ich den TCP-Verkehr auf einem Socket?

Wie verzögere ich den TCP-Verkehr auf einem Socket?

Ich möchte die Interaktionen zwischen einem Client-Programm und einem Server-Programm auf Race Conditions testen. Sie stellen über TCP eine Verbindung zueinander her. Der Client führt blockierende Aufrufe an den Server über mehrere Threads aus (eine TCP-Verbindung zum Server pro Thread). Ich möchte den Race Condition testen, bei dem ein blockierender Aufruf vor dem anderen beendet wird.

Dazu wollte ich die TCP-Verbindungen um unterschiedliche Beträge verzögern (damit ich weder den Client noch den Server explizit neu schreiben muss).

Ich hatte gehofft, so etwas zu tun:

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

wobei $pinder Port ist, mit dem sich der Client verbindet, $delaydie Anzahl der Sekunden, die verzögert werden sollen, und $poutder Port ist, auf dem der Server lauscht. Und delaycatist ein imaginäres Programm, das den Eingabestrom um n Sekunden verzögert.

Gibt es bereits ein Programm, das das macht, was ich will? Oder soll ich schreiben delaycat?

Bearbeiten:Beachten Sie, dass eine systemweite Verzögerung nicht wirklich ideal wäre, da ich die einzelnen Sockets nach Möglichkeit unterschiedlich verzögern möchte.

Antwort1

Ich konnte nichts finden, was es bereits gibt, also habe ich ein Python-Skript geschrieben, um Folgendes zu tun (das ist wahrscheinlich fehlerhaft):

#!/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()

Antwort2

Auf einem Linux-Rechner können Sie tc verwenden mitNetem.

Beispielsweise tc qdisc add dev eth0 root netem delay 100msverzögert der Befehlalleausgehende Pakete um 100 Millisekunden. Um eingehende Pakete zu verzögern, können Sie dieifb - Zwischenfunktionsblock

verwandte Informationen