前提
python3.9を用いて,UDP/TCPによるソケット通信を行っています.サーバは,複数のクライアントからUDPでデータを受け取り,そのデータを加工し,TCPでクライアントに返送します.
実現したいこと
複数のクライアントからのUDPのデータを一台のサーバで並列(非同期)で捌きたいと考えています.
その際に,asyncioでタスクを複数作り,同時にUDPデータをrecvfrom()したいと考えています
発生している問題・エラーメッセージ
1つ目のクライアントからのデータは正常に受け取れますが,2つめのクライアントからのデータは受け取れず,recvfromがそのままタイムアウトしてしまいます.
ちなみに,asyncioは並列処理ではなく,シングルスレッドで動作していることは理解していますが,全く知見はありません.
該当のソースコード
10つのクライアントからUDPを受信しようと考えているため,def main()内のfor処理を10回繰り返し,10個のタスクを生成しています.
※主にソケット生成/受信/送信部分を見てもらえればよいと思います.
async.py
1import socket 2import asyncio 3 4 5M_Group = "239.1.2.3" 6LOCALHOST = socket.gethostbyname(socket.gethostname()) 7PORT = 1234 8 9 10FILE_NAME = 'send.txt' 11 12# UDPソケットの設定 13udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 14udp_sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(LOCALHOST)) 15udp_sock.setsockopt( 16 socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, 17 socket.inet_aton(M_Group) + socket.inet_aton(LOCALHOST) 18) 19# 自分の送ったマルチキャストパケットを自身で受け取らない 20udp_sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 0) 21udp_sock.bind(('', PORT)) 22udp_sock.settimeout(5) 23 24# udp_sock.connect((M_Group, PORT)) 25 26# TCPソケットの設定 27tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 28 29 30file_data = "" 31len_data = 0 32 33with open(FILE_NAME, 'r') as f: 34 file_data = f.read() 35 len_data = len(file_data) 36 37 38async def recv_loss_packet(): 39 40 print("time to wait for response...") 41 try: 42 res_data, (src_ip, src_port) = udp_sock.recvfrom(1024) 43 44 print(f'src_ip: {src_ip}, src_port: {src_port}') 45 46 47 # packet loss seq split 48 recv_seq_ary = res_data.decode().split(",") 49 recv_seq_ary.pop(-1) 50 51 recv_seq_ary = list(map(int, recv_seq_ary)) 52 print(recv_seq_ary) 53 54 # packet loss data resend 55 tcp_sock.connect((src_ip, src_port)) 56 57 for i in recv_seq_ary: 58 chunk = file_data[i*10:i*10+10] 59 chunk = str(i) + ":" + chunk 60 print(chunk) 61 62 tcp_sock.send(chunk.encode()) 63 64 except: 65 print(f"Timeout!") 66 67 68async def main(): 69 count = 0 70 71 # データを指定バイトごとに分割 72 chunks = [file_data[i:i+10] for i in range(0, len_data, 10)] 73 74 for chunk in chunks: 75 count+=1 76 chunk = str(count) + ":" + chunk 77 print(chunk) 78 79 udp_sock.sendto(chunk.encode(), (M_Group, PORT)) 80 time.sleep(0.05) 81 82 for i in range(10): 83 asyncio.create_task(recv_loss_packet()) 84 85 await asyncio.sleep(10) 86 87asyncio.run(main()) 88
試したこと
"発生している問題"でも述べましたが,2つのクライアントで試してみたところ,1つめのクライアントからは受け取れて,2つめのクライアントからは,データを受け取れませんでした.
並列処理ではないため,2つのクライアントからの送信を,十分な間隔(2秒)を空けて送信しましたが結果は変わりませんでした.

回答1件
あなたの回答
tips
プレビュー