回答編集履歴

3

コードの修正

2022/12/22 09:58

投稿

Yochyee
Yochyee

スコア2

test CHANGED
@@ -1,5 +1,5 @@
1
1
  udpのsocketをnon blockingにし,add_readerでイベントを登録することで実装できました.
2
- **ちなみにwindowsでは,asyncio.get_event_loop()が使えないようです.**
2
+ **ちなみに私の環境であるwindowsでは,asyncio.get_event_loop()が使えないようなの代替記法で書いています.**
3
3
 
4
4
  本質問では,UDPで受信した後,TCPで返送するプログラムでしたがTCP部分が正常に動かなかったため.TCPの部分は削除しました.
5
5
 
@@ -59,6 +59,7 @@
59
59
 
60
60
 
61
61
  # イベントループの取得 & セット
62
+ # 以下3行は,windows以外なら,asyncio.get_event_loop() のみで良い
62
63
  selector = selectors.SelectSelector()
63
64
  loop = asyncio.SelectorEventLoop(selector)
64
65
  asyncio.set_event_loop(loop)

2

コードの修正

2022/12/22 09:56

投稿

Yochyee
Yochyee

スコア2

test CHANGED
@@ -18,7 +18,9 @@
18
18
  # 自分の送ったマルチキャストパケットを自身で受け取らない
19
19
  udp_sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 0)
20
20
  udp_sock.bind(('', PORT))
21
+
22
+ # ノンブロッキングに指定
21
- udp_sock.settimeout(5)
23
+ udp_sock.setblocking(False)
22
24
 
23
25
 
24
26
  FILE_NAME = 'send.txt'
@@ -56,15 +58,17 @@
56
58
  time.sleep(0.05)
57
59
 
58
60
 
59
- # + 追加した部分
61
+ # イベントループの取得 & セット
60
- + selector = selectors.SelectSelector()
62
+ selector = selectors.SelectSelector()
61
- + loop = asyncio.SelectorEventLoop(selector)
63
+ loop = asyncio.SelectorEventLoop(selector)
62
- + asyncio.set_event_loop(loop)
64
+ asyncio.set_event_loop(loop)
63
65
 
66
+ # udp_sockのファイルディスクリプタが空いたら,紐づけられた関数を実行
64
- + loop.add_reader(udp_sock.fileno(), recv_loss_packet)
67
+ loop.add_reader(udp_sock.fileno(), recv_loss_packet)
65
68
 
69
+ # ループを回す
66
- + try:
70
+ try:
67
- + loop.run_forever()
71
+ loop.run_forever()
68
- + finally:
72
+ finally:
69
- + loop.close()
73
+  loop.close()
70
74
  ```

1

ソースの変更

2022/12/22 09:52

投稿

Yochyee
Yochyee

スコア2

test CHANGED
@@ -1,20 +1,70 @@
1
1
  udpのsocketをnon blockingにし,add_readerでイベントを登録することで実装できました.
2
- ちなみにwindowsでは,asyncio.get_event_loop()が使えないようです.
2
+ **ちなみにwindowsでは,asyncio.get_event_loop()が使えないようです.**
3
+
4
+ 本質問では,UDPで受信した後,TCPで返送するプログラムでしたがTCP部分が正常に動かなかったため.TCPの部分は削除しました.
3
5
 
4
6
  ```async.py
7
+ M_Group = "239.1.2.3"
8
+ LOCALHOST = socket.gethostbyname(socket.gethostname())
5
- import socket
9
+ PORT = 1234
6
- import asyncio
7
- import selectors
8
10
 
9
- # ループイベントのget & set (windowsのみの記法)
11
+ # UDPソケットの設定
10
- selector = selectors.SelectSelector()
12
+ udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
13
+ udp_sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(LOCALHOST))
14
+ udp_sock.setsockopt(
15
+ socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP,
11
- loop = asyncio.SelectorEventLoop(selector)
16
+ socket.inet_aton(M_Group) + socket.inet_aton(LOCALHOST)
17
+ )
18
+ # 自分の送ったマルチキャストパケットを自身で受け取らない
19
+ udp_sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 0)
20
+ udp_sock.bind(('', PORT))
12
- asyncio.set_event_loop(loop)
21
+ udp_sock.settimeout(5)
13
22
 
14
- loop.add_reader(udp_sock.fileno(), recv_loss_packet)
15
23
 
24
+ FILE_NAME = 'send.txt'
25
+ file_data = ""
26
+ len_data = 0
27
+
28
+ with open(FILE_NAME, 'r') as f:
29
+ file_data = f.read()
30
+ len_data = len(file_data)
31
+
32
+
33
+ def recv_loss_packet():
34
+
35
+ print("time to wait for response...")
16
- try:
36
+ try:
37
+ res_data, (src_ip, src_port) = udp_sock.recvfrom(1024)
38
+
39
+ print(f'src_ip: {src_ip}, src_port: {src_port}')
40
+
41
+ except:
42
+ print(f"Timeout!")
43
+
44
+
45
+ count = 0
46
+
47
+ # データを指定バイトごとに分割
48
+ chunks = [file_data[i:i+10] for i in range(0, len_data, 10)]
49
+
50
+ for chunk in chunks:
51
+ count+=1
52
+ chunk = str(count) + ":" + chunk
53
+ print(chunk)
54
+
55
+ udp_sock.sendto(chunk.encode(), (M_Group, PORT))
56
+ time.sleep(0.05)
57
+
58
+
59
+ # + 追加した部分
60
+ + selector = selectors.SelectSelector()
61
+ + loop = asyncio.SelectorEventLoop(selector)
62
+ + asyncio.set_event_loop(loop)
63
+
64
+ + loop.add_reader(udp_sock.fileno(), recv_loss_packet)
65
+
66
+ + try:
17
- loop.run_forever()
67
+ + loop.run_forever()
18
- finally:
68
+ + finally:
19
- loop.close()
69
+ + loop.close()
20
70
  ```