Почему сокет не закрывается при закрытии программы?

gastrit

Новичок
Пользователь
Апр 23, 2020
4
0
1
Python:
import tkinter as tk
from tkinter import *
import socket
import threading


client = []
global sock
stop_potok = False
SOCKET_LIST = {}

def stop_serv():
    global stop_potok
    global potok
    start_but.config(state = NORMAL)
    stop_but.config(state = DISABLED)
    
    stateLabel.config(text='Сервер не работает', fg = 'red', font = 16)
    stop_potok = True
    sock.close()



def read_sok():

    global stop_potok

    while 1:

        if stop_potok:
            print("стоп")
            break

        data , addres = sock.recvfrom(1024)
        print (addres[0], addres[1])
        if  addres not in client :
                client.append(addres)# Если такова клиента нету , то добавить
        for clients in client :
                if clients == addres :
                    continue # Не отправлять данные клиенту который их прислал
                sock.sendto(data,clients)

    sock.close()
 


def start_serv():
    global stop_potok
    global sock
    global potok
    IpADD = IP.get()
    PORT = int(port.get())
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind((IpADD,PORT))
    
    SOCKET_LIST['Host'] = sock

    try:
        start_but.config(state = DISABLED)
        stop_but.config(state = NORMAL)

        stateLabel.config(text='Сервер работает', fg = 'green', font = 16)

    except BaseException as excp:
        stateLabel.config(text=excp, fg = 'red', font = 16)

    
    stop_potok=False
    potok = threading.Thread(target= read_sok)
    potok.start()



serverWindow = tk.Tk()
serverWindow.title("Сервер")

serverWindow.geometry("300x400+200+255")

IPFrame = Frame(serverWindow)
PortFrame = Frame(serverWindow)


Label(IPFrame, text="IP: ", font = 15).pack(side = LEFT,  pady = 15, padx = 20)
IP = Entry(IPFrame, font={15})
IP.insert(END, '127.0.0.1')
IP.pack(side = RIGHT,  pady = 15, padx = 20, fill=X)

Label(PortFrame, text="PORT: ", font = 15).pack(side = LEFT, pady = 15, padx = 20)
port = Entry(PortFrame, font={15})
port.insert(END, '8080')
port.pack(side = RIGHT, pady = 15, padx = 20, fill=X)

IPFrame.pack()
PortFrame.pack()


start_but = Button(serverWindow, text = 'Старт', command = start_serv, font = 15,  pady = 15, width = 50)
start_but.pack(  pady = 15)
stop_but = Button(serverWindow, text = 'Стоп', command = stop_serv, state=DISABLED, font = 15,  pady = 15, width = 50)
stop_but.pack(  pady = 15)

stateLabel = Label(serverWindow,  pady = 15)
stateLabel.pack(pady = 15)



serverWindow.mainloop()

stop_potok = True

sock.close()
 

stud_55

Модератор
Команда форума
Модератор
Апр 3, 2020
1 522
672
113
Вот немного измененный код вашего сервера, который может закрыть сокет:
Python:
import tkinter as tk
import socket
import time
import threading


client = []
global sock
stop_potok = False
SOCKET_LIST = {}


def stop_serv():
    global stop_potok
    global potok

    start_but.config(state=tk.DISABLED)
    stop_but.config(state=tk.DISABLED)

    stateLabel.config(text='Сервер завершает работу', fg='red', font=16)

    stop_potok = True


def read_sok():
    global stop_potok

    while not stop_potok:
        print(sock)
        try:
            conn, addr = sock.recvfrom(1024)
            if conn and addr:
                print(conn, addr)
                sock.sendto(bytes('Сообщение от сервера', 'utf-8'), addr)
        except Exception as e:
            print(e)

        time.sleep(1)

    print('Поток завершен')
    if stop_potok:
        sock.close()
        print('сокет закрыт')
        start_but.config(state=tk.NORMAL)
        stop_but.config(state=tk.DISABLED)
        stateLabel.config(text='Сервер не работает', fg='red', font=16)


def start_serv():
    global stop_potok
    global sock
    global potok
    IpADD = IP.get()
    PORT = int(port.get())
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.settimeout(3.0)
    sock.bind((IpADD, PORT))
    SOCKET_LIST['Host'] = sock

    try:
        start_but.config(state=tk.DISABLED)
        stop_but.config(state=tk.NORMAL)

        stateLabel.config(text='Сервер работает', fg='green', font=16)

    except BaseException as excp:
        stateLabel.config(excp, fg='red', font=16)

    stop_potok = False
    potok = threading.Thread(target=read_sok)
    potok.start()


serverWindow = tk.Tk()
serverWindow.title("Сервер")

serverWindow.geometry("300x400+200+255")

IPFrame = tk.Frame(serverWindow)
PortFrame = tk.Frame(serverWindow)


tk.Label(IPFrame, text="IP: ", font=15).pack(side=tk.LEFT, pady=15, padx=20)
IP = tk.Entry(IPFrame, font={15})
IP.insert(tk.END, '127.0.0.1')
IP.pack(side=tk.RIGHT, pady=15, padx=20, fill=tk.X)

tk.Label(PortFrame, text="PORT: ", font=15).pack(side=tk.LEFT, pady=15, padx=20)
port = tk.Entry(PortFrame, font={15})
port.insert(tk.END, '8080')
port.pack(side=tk.RIGHT, pady=15, padx=20, fill=tk.X)

IPFrame.pack()
PortFrame.pack()

start_but = tk.Button(serverWindow, text='Старт', command=start_serv, font=15, pady=15, width=50)
start_but.pack(pady=15)
stop_but = tk.Button(serverWindow, text='Стоп', command=stop_serv, state=tk.DISABLED, font=15, pady=15, width=50)
stop_but.pack(pady=15)
stateLabel = tk.Label(serverWindow, pady=15)
stateLabel.pack(pady=15)
serverWindow.mainloop()
и клиент к нему:
Python:
import socket
import sys

host = 'localhost'
port = 8080
addr = (host, port)

udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)


data = input('Сообщение серверу: ')
if not data:
    udp_socket.close()
    sys.exit(1)


data = bytes(data, 'utf-8')
udp_socket.sendto(data, addr)
data = bytes.decode(data)
data = udp_socket.recvfrom(1024)
data = (data[0].decode('utf-8'), data[1])
print(data)


udp_socket.close()
 

borntohack

змееуст
Команда форума
Модератор
Апр 22, 2020
78
62
18
39
Москва, РФ
potok.join() напишите. Там у вас бесконечный цикл, который не дает закрыть используемый на read сокет
 

gastrit

Новичок
Пользователь
Апр 23, 2020
4
0
1
potok.join() напишите. Там у вас бесконечный цикл, который не дает закрыть используемый на read сокет
когда пишу join на кнопку Стоп то прога зависает, когда пишу последней строчкой все равно висит. Куда этот join писать?
 

stud_55

Модератор
Команда форума
Модератор
Апр 3, 2020
1 522
672
113
Сокет ожидает данные, вот в этой строке кода:
Python:
data , addres = sock.recvfrom(1024)
поэтому цикл останавливается и вызова
Python:
sock.close()
не происходит
 
  • Мне нравится
Реакции: gastrit

gastrit

Новичок
Пользователь
Апр 23, 2020
4
0
1
Сокет ожидает данные, вот в этой строке кода:
Python:
data , addres = sock.recvfrom(1024)
поэтому цикл останавливается и вызова
Python:
sock.close()
не происходит
я же повесил
Python:
sock.close()
на stop_serv(). Почему не срабатывает? Как это исправить?
 

stud_55

Модератор
Команда форума
Модератор
Апр 3, 2020
1 522
672
113
я же повесил
Python:
sock.close()
на stop_serv(). Почему не срабатывает? Как это исправить?
Не срабатывает потому что из-за ожидания данных цикл останавливается и выхода из него не происходит. Даже если следующей строкой после:
Python:
data , addres = sock.recvfrom(1024)
прописать
Python:
sock.close()
сокет все равно не закроется, так как эта строка не выполнится так как сокет ожидает данные.
Чтобы исправить можно задать таймаут, например 3 секунды sock.settimeout(3.0) чтобы сокет вышел из ожидания и выдал исключение timed out, его нужно обработать. Тогда цикл продолжится и сможет завершиться. А потом отработает закрытие сокета.
 

Форум IT Специалистов