소켓에서 TCP 트래픽을 어떻게 지연합니까?

소켓에서 TCP 트래픽을 어떻게 지연합니까?

경쟁 조건에 대해 클라이언트 프로그램과 서버 프로그램 간의 상호 작용을 테스트하고 싶습니다. 그들은 tcp를 통해 서로 연결됩니다. 클라이언트는 여러 스레드에서 서버에 대한 호출을 차단합니다(스레드당 서버에 대한 하나의 tcp 연결). 하나의 차단 호출이 다른 호출보다 먼저 완료되는 경쟁 조건을 테스트하고 싶습니다.

이를 위해 나는 tcp 연결을 다양한 양만큼 지연하기를 바랐습니다(따라서 클라이언트나 서버를 명시적으로 다시 작성할 필요가 없습니다).

나는 다음과 같은 일을 하고 싶었습니다.

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

$pin는 클라이언트가 연결하는 포트이고, 는 $delay지연 시간(초)이며, $pout는 서버가 수신 대기하는 포트입니다. 그리고 delaycat입력 스트림을 n초 지연시키는 가상의 프로그램입니다.

내가 원하는 것을 수행하는 기존 프로그램이 있습니까? 아니면 글을 써야 할까요 delaycat?

편집하다:가능하다면 개별 소켓을 다른 양만큼 지연시키고 싶기 때문에 시스템 전체 지연은 실제로 이상적이지 않습니다.

답변1

이미 거기에서 아무것도 찾을 수 없어서 이를 수행하기 위해 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()

답변2

리눅스 머신에서는 tc를 다음과 같이 사용할 수 있습니다.네템.

예를 들어, 명령은 tc qdisc add dev eth0 root netem delay 100ms지연됩니다모두나가는 패킷을 100밀리초씩 늘립니다. 들어오는 패킷을 지연하려면 다음을 사용할 수 있습니다.ifb - 중급 기능 블록

관련 정보