64177


私は以下のようなUDP送受信のコードを書きました。  
1秒ごとに送信するコード(udpSend.py)と、1秒ごとに待ち受けるコード(udpRecv.py)です。  
最初、udpRecv.pyのtimeout値を0.1に設定し、次にtimeout値を5に変更して試してみました。

**udpSend.py**

[code]

    import time
    import threading
    from socket import socket, AF_INET, SOCK_DGRAM
    
    HOST = ''
    PORT = 5000
    ADDRESS = "127.0.0.1" # 自分に送信
    
    s = socket(AF_INET, SOCK_DGRAM)
    startTime = time.time()
    
    def worker():
        try:
            msg = str(time.time()-startTime)
            print(msg)
            s.sendto(msg.encode(), (ADDRESS, PORT))
            time.sleep(8)
        except:
            pass
    
    def scheduler(interval, f, wait = True):
        base_time = time.time()
        next_time = 0
        while True:
            t = threading.Thread(target = f)
            t.start()
            if wait:
                t.join()
            next_time = ((base_time - time.time()) % interval) or interval
            time.sleep(next_time)
    
    scheduler(1, worker, False)
    
[/code]

**udpRecv.py**

[code]

    import time
    import threading
    from socket import socket, AF_INET, SOCK_DGRAM
    
    HOST = ''   
    PORT = 5000
    
    # ソケットを用意
    s = socket(AF_INET, SOCK_DGRAM)
    # バインドしておく
    s.bind((HOST, PORT))
    s.settimeout(0.1)
    
    def worker():
        try:
            msg, address = s.recvfrom(8192)
            print(msg.decode('utf-8'))
            time.sleep(8)
        except:
            pass
    
    def scheduler(interval, f, wait = True):
        base_time = time.time()
        next_time = 0
        while True:
            t = threading.Thread(target = f)
            t.start()
            if wait:
                t.join()
            next_time = ((base_time - time.time()) % interval) or interval
            time.sleep(next_time)
    
    scheduler(1, worker, False)
    
[/code]

そうすると、以下のような出力結果が得られました。

**・timeout値=0.1の時** (左側の出力が送信元、右側の出力が受信側)  
[![画像の説明をここに入力](https://i.stack.imgur.com/HGYLP.gif)](https://i.stack.imgur.com/HGYLP.gif)

**・timeout値=5の時** (左側の出力が送信元、右側の出力が受信側)  
[![画像の説明をここに入力](https://i.stack.imgur.com/JTWoH.gif)](https://i.stack.imgur.com/JTWoH.gif)

上記の画像から、  
timeout値が0.1の時は1秒近い遅延があるのに対し、timeout値が5の時は遅延がほぼない状態に見えます。  
これはどういった仕組みで遅延が発生しているのでしょうか？

この場合ではtimeout値を大きくした方が望み通りの結果になっています。  
しかし、必ずしもtimeout値を大きくすれば良いというわけでもないのではないかと思うのですが、  
どういった時にtimeout値を大きくしたり小さくしたりすれば良いのでしょうか？


CC BY-SA 4.0
2020-03-27T16:40:15.897
64165
2020-03-28T07:00:08.527
34471
question
python network socket
Socket通信のタイムアウト値と遅延の関係について知りたい


# timeout = 0.1

[code]

    msg, address = s.recvfrom(8192)
    
[/code]

受信スレッドが起動されて0.1秒以内にデータが来なければ、データが読まれるのは次に受信スレッドが起動されたタイミングですので、0.1～0.9秒のタイムラグが生じます。送受信とも1秒ごとに動作するので以後このタイムラグは維持されます。

# timeout = 5

[code]

    msg, address = s.recvfrom(8192)
    
[/code]

5秒待つ受信スレッドが毎秒起動されるので、データが届いたタイミングで必ず1つはスレッドが生きています。ですので、到達したデータはほぼリアルタイムで読み込まれます。

> しかし、必ずしもtimeout値を大きくすれば良いというわけでもないのではないかと思うのですが、

これはその通りです。が、一般論として「大きくすればよい」「小さくすればよい」という話ではありません。何がやりたいか次第です。

受信スレッドが1秒ごとに起動されるのが前提なら、タイムアウトは1秒以上あっても意味がありません。が、目的に対して受信スレッドを1秒ごとに起動する、という方法自体が妥当でないのであれば、それについてタイムアウトをどうするかの議論も無意味になります。


CC BY-SA 4.0
2020-03-28T07:00:08.527
64177
2020-03-28T07:00:08.527
5793
64165
answer