Как я прерываю socket.recv () от другого потока в Python

У меня есть основной поток, который ожидает соединения. Это порождает клиентские потоки, которые повторят ответ от клиента (telnet в этом случае). Но скажите, что я хочу закрыть все сокеты и все потоки через какое-то время, как после 1 соединения.

Как я сделал бы это? Если я делаю clientSocket.close() от основного потока это не прекратит делать recv. Это только остановится, если я сначала отправлю что-то через telnet, то затем это перестанет работать, выполнение далее отправляет и recvs.

Мой код похож на это:

# Echo server program
import socket
from threading import Thread
import time

class ClientThread(Thread):
    def __init__(self, clientSocket):
            Thread.__init__(self)
            self.clientSocket = clientSocket

    def run(self):
            while 1:
                    try:
                            # It will hang here, even if I do close on the socket
                            data = self.clientSocket.recv(1024)
                            print "Got data: ", data
                            self.clientSocket.send(data)
                    except:
                            break

            self.clientSocket.close()

HOST = ''
PORT = 6000
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
serverSocket.bind((HOST, PORT))
serverSocket.listen(1)

clientSocket, addr = serverSocket.accept()
print 'Got a new connection from: ', addr
clientThread = ClientThread(clientSocket)
clientThread.start()

time.sleep(1)

# This won't make the recv in the clientThread to stop immediately,
# nor will it generate an exception
clientSocket.close()
14
задан Francesco Boi 6 January 2019 в 16:26
поделиться

2 ответа

Не знаю, можно ли сделать то, о чем вы просите, но в этом нет необходимости. Только не читайте из сокета, если читать нечего; используйте select.select , чтобы проверить сокет на наличие данных.

изменить:

data = self.clientSocket.recv(1024)
print "Got data: ", data
self.clientSocket.send(data)

на что-то вроде этого:

r, _, _ = select.select([self.clientSocket], [], [])
if r:
    data = self.clientSocket.recv(1024)
    print "Got data: ", data
    self.clientSocket.send(data)

РЕДАКТИРОВАТЬ: Если вы хотите предотвратить возможность закрытия сокета, перехватите socket.error .

do_read = False
try:
    r, _, _ = select.select([self.clientSocket], [], [])
    do_read = bool(r)
except socket.error:
    pass
if do_read:
    data = self.clientSocket.recv(1024)
    print "Got data: ", data
    self.clientSocket.send(data)
6
ответ дан 1 December 2019 в 09:31
поделиться

Я нашел решение, используя таймауты. Это прервет recv (на самом деле до истечения тайм-аута, что приятно):

# Echo server program
import socket
from threading import Thread
import time


class ClientThread(Thread):
    def __init__(self, clientSocke):
        Thread.__init__(self)
        self.clientSocket = clientSocket

    def run(self):
        while 1:
            try:
                data = self.clientSocket.recv(1024)
                print "Got data: ", data
                self.clientSocket.send(data)
            except socket.timeout: 
                # If it was a timeout, we want to continue with recv
                continue
            except:
                break

        self.clientSocket.close()

HOST = ''
PORT = 6000
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
serverSocket.bind((HOST, PORT))
serverSocket.listen(1)

clientSocket, addr = serverSocket.accept()
clientSocket.settimeout(1)

print 'Got a new connection from: ', addr
clientThread = ClientThread(clientSocket)
clientThread.start()

# Close it down immediatly 
clientSocket.close()
3
ответ дан 1 December 2019 в 09:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: