61138


以下のようにPythonを使って、一定間隔でUDP通信するプログラムを書いています。

GUIの右上の閉じるボタンを押してプログラムを終了させた場合、スレッドは  
`self.thread.setDaemon(True)` によって終了するのですが、socketは `close()`
されないまま終わってしまっています。(Stopボタンを押した場合はsocketはclose()されます)

[![画像の説明をここに入力](https://i.stack.imgur.com/O5ZPk.jpg)](https://i.stack.imgur.com/O5ZPk.jpg)

このように `close()` されずにプログラムが終了した場合、どのような問題がありますか？  
また、右上の閉じるボタンでプログラムを終了した場合でもsocketを `close()` するにはどうしたらよいですか？

* * *

**ソースコード**

[code]

    import tkinter as tk
    import threading
    import time
    from socket import socket, AF_INET,SOCK_DGRAM,SOL_SOCKET,SO_BROADCAST,SOCK_STREAM
    
    class threading_and_sleepGUI():
        def __init__(self):
            self.stop_flag=False
            self.thread=None
            self.s = None
    
        def worker(self):
            msg = "test"
            self.s.sendto(msg.encode(), ("127.0.0.1", 8888))
            time.sleep(8)
    
        def scheduler(self,interval, f, wait = True):
            base_time = time.time()
            next_time = 0
            while not self.stop_flag:
                t = threading.Thread(target = f)
                t.start()
                if wait:
                    t.join()
                next_time = ((base_time - time.time()) % interval) or interval
                time.sleep(next_time)
    
        def start(self):
            if not self.thread:
                self.s = socket(AF_INET, SOCK_DGRAM)
                self.s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
    
                self.thread = threading.Thread(target=self.scheduler, args=(1, self.worker, False))
                self.thread.setDaemon(True)
                self.stop_flag=False
                self.thread.start()
    
        def stop(self):
            if self.thread:
                self.s.close()
                self.stop_flag=True
                self.thread.join()
                self.thread=None
    
        def GUI_start(self):
            root=tk.Tk()
            Button001=tk.Button(root,text="Start",command=self.start)
            Button001.pack()
            Button002=tk.Button(root,text="Stop",command=self.stop)
            Button002.pack()
            root.mainloop()
    
    t = threading_and_sleepGUI()
    t.GUI_start()
    
[/code]


CC BY-SA 4.0
2019-12-05T08:07:53.860
61132
2019-12-05T17:11:36.287
2019-12-05T17:11:36.287
3060
34471
question
python network socket udp
プログラムが意図しない終了方法をした時の、socketのclose()について


プログラム（プロセス）が終了したら、そこで使われていたソケットなどはcloseされますから、心配いりません。  
パケットが届かない可能性があるUDP通信ですから、受信側にも影響ないです。


CC BY-SA 4.0
2019-12-05T09:18:11.130
61138
2019-12-05T09:18:11.130
217
61132
answer


@Fumu 7
さん回答のように、ソケットやファイル等の資源についてはcloseされるとしても、何かしらの後始末はやっておきたい場合は、[root.protocol("WM_DELETE_WINDOW",
callback)](https://effbot.org/tkinterbook/tkinter-events-and-
bindings.htm#protocols) を使ってイベントハンドラを登録しておくと、それが呼ばれるようです。

ただし.afterで周期的に(多分マルチスレッドでの処理も含んで)何かしている場合は、処理ループの実行中でもそれが呼び出されるので、単純に終了処理`destroy()`を呼ぶのは不味くて、フラグを立ててループを終了するなど、後始末は工夫しましょう、という回答が以下の記事にあるようです。  
[How do I handle the window close event in
Tkinter?](https://stackoverflow.com/q/111155/9014308)

Upvoteは無いですが、こちらの回答ですね。  
<https://stackoverflow.com/a/58469034/9014308>


CC BY-SA 4.0
2019-12-05T09:49:09.817
61141
2019-12-05T09:49:09.817
26370
61132
answer