在python中模拟慢速网络的简单方法

Orj*_*anp 7 python networking network-programming

场景.我有一个客户端与服务器的两个网络连接.一个连接使用移动​​电话,另一个连接使用wlan连接.

我解决这个问题的方法是让服务器监听两个端口.但是,移动连接应该比wlan连接慢.发送的数据通常只是一行文本.我通过允许移动连接以五秒间隔发送数据解决了较慢的连接问题,wlan连接的间隔为一秒.

但是有更好的方法来减速吗?也许通过发送较小的数据包,这意味着我需要发送更多数据?

有什么想法可以减缓其中一个连接的速度?

Orjanp

一个只有一个连接的简单客户端示例.

def client():
    import sys, time, socket

    port = 11111
    host = '127.0.0.1'
    buf_size = 1024

    try:
        mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        mySocket.connect((host, port))
    except socket.error, (value, message):
        if mySocket:
            mySocket.close()
        print 'Could not open socket: ' + message
        sys.exit(1)
    mySocket.send('Hello, server')
    data = mySocket.recv(buf_size)
    print data
    time.sleep(5)

    mySocket.close()

client()
Run Code Online (Sandbox Code Playgroud)

一个简单的服务器,监听一个端口.

def server():
    import sys, os, socket

    port = 11111
    host = ''
    backlog = 5
    buf_size = 1024

    try:
        listening_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        listening_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 
        listening_socket.bind((host, port)) 
        listening_socket.listen(backlog)
    except socket.error, (value, message):
        if listening_socket:
            listening_socket.close()
        print 'Could not open socket: ' + message
        sys.exit(1)

    while True:
        accepted_socket, adress = listening_socket.accept()
        data = accepted_socket.recv(buf_size)
        if data:
            accepted_socket.send('Hello, and goodbye.')
        accepted_socket.close()

server()
Run Code Online (Sandbox Code Playgroud)

Jea*_*one 10

除了使用外部工具来模拟您感兴趣的网络类型之外,一种好的方法是使用套接字的替代实现.

这涉及使套接字构造成为函数的参数,而不是导入套接字模块并直接使用它.对于正常操作,您将传入真正的套接字类型,但是当您想要测试各种不利的网络条件时,您可以传入模拟这些条件的实现.例如,您可以创建一个套接字类型,用于参数化延迟和带宽(未经测试的代码,请注意):

import time, socket

class ControllableSocket:
    def __init__(self, latency, bandwidth):
        self._latency = latency
        self._bandwidth = bandwidth
        self._bytesSent = 0
        self._timeCreated = time.time()
        self._socket = socket.socket()

    def send(self, bytes):
        now = time.time()
        connectionDuration = now - self._timeCreated
        self._bytesSent += len(bytes)
        # How long should it have taken to send how many bytes we've sent with our
        # given bandwidth limitation?
        requiredDuration = self._bytesSent / self._bandwidth
        time.sleep(max(requiredDuration - connectionDuration, self._latency))
        return self._socket.send(bytes)
Run Code Online (Sandbox Code Playgroud)

如果实现其他套接字方法connect,recv等,则可以将此类的实例替换为实际套接字类型的实例.这使得程序的所有其余部分完全不受任何模拟知识的影响,简化了它,同时还允许您通过实现模拟它们的新套接字类型来尝试许多不同的网络配置.

这个想法是Twisted明确区分"协议"概念的原因之一 - 这些协议知道如何从网络中解释字节并生成新的字节以发送到网络 - 来自"传输" - 知道如何关闭字节的对象网络并将字节放到它上面.分离简化了测试并允许像这样的新配置,其中由传输提供对一些其他网络条件(可能难以实际产生)的模拟.