如何从Python中的另一个线程中止socket.recv()

Sam*_*erg 14 python sockets multithreading recv

我有一个等待连接的主线程.它产生的客户端线程将回应客户端的响应(在本例中为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()
Run Code Online (Sandbox Code Playgroud)

ceb*_*bru 17

我知道这是一个老话题,塞缪尔可能很久以前就解决了他的问题.但是,我有同样的问题,并在google'ing时遇到了这篇文章.找到了解决方案并认为值得添加.

您可以在套接字类上使用shutdown方法.它可以防止进一步发送,接收或两者.

socket.shutdown(socket.SHUT_WR)

以上是为了防止将来的发送,作为一个例子.

有关详细信息,请参阅Python文档.


Mat*_*son 6

我不知道是否可以做你所要求的,但它不应该是必要的.如果没有什么可读的,请不要从套接字读取; 用于select.select检查套接字的数据.

更改:

data = self.clientSocket.recv(1024)
print "Got data: ", data
self.clientSocket.send(data)
Run Code Online (Sandbox Code Playgroud)

更像这样的事情:

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

编辑:如果你想防止插座已经关闭的可能性,赶上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)
Run Code Online (Sandbox Code Playgroud)