Python在线程中处理Socketserver请求

1 投票
3 回答
3841 浏览
提问于 2025-04-17 08:30

在下面这个例子中,我有一个在线程中处理的Socket服务器。在处理函数里,我们创建了一个线程,并传入了请求和客户端的地址。当我们在线程的运行方法中处理请求时,只能接收数据,但当我尝试发送数据时,就会出现一个错误([Errno 9] 错误的文件描述符)。这是什么问题呢?

import SocketServer
import threading


class MyServerThread(threading.Thread):

    def __init__(self, channel, details):
        self.channel = channel
        self.details = details
        threading.Thread.__init__(self)

    def run(self):
        print 'Received connection:', self.details[0]
        self.channel.send('(Response)')
        print 'Received:', self.channel.recv(1024)
        self.channel.close()
        print 'Closed connection:', self.details[0]


class MyThreadedSocketServerHandler(SocketServer.BaseRequestHandler):

    def handle(self):
        thread1 = MyServerThread(self.request, self.client_address)
        thread1.start()

if __name__ == '__main__':
    server = SocketServer.TCPServer(('localhost', 8888), MyThreadedSocketServerHandler)
    server.serve_forever()


#---Client to test---
import socket

message = "(Request)"

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
    sock.connect(('localhost', 8888))
    sock.send(message)
    data = sock.recv(1024)
    print 'Sent:     %s' % message
    print 'Received: %s' % data
finally:
    sock.close()




#Working example without "join"
import socket
import threading

class ClientThread(threading.Thread):

    def __init__(self, channel, details):
        self.channel = channel
        self.details = details
        threading.Thread.__init__(self)

    def run(self):
        print 'Received connection:', self.details[0]
        self.channel.send('message')
        print self.channel.recv(1024)
        self.channel.close()
        print 'Closed connection:', self.details[0]

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('', 8888))
server.listen(5)

while True:
    channel, details = server.accept()
    ClientThread(channel, details).start()

3 个回答

0

你的问题是:

thread1.start()

上面的代码会立即返回,MyServerThread.run() 在后台运行。所以 MyThreadedSocketServerHandler.handle() 会在 MyServerThread.run() 执行之前就返回。当 handle() 函数返回后,self.request 就会被关闭,你的客户端什么也收不到。当 MyServerThread.run() 被执行时,self.request.send() 会失败,因为这个连接已经关闭了。

所以要在:

thread1.join()

之后添加:

0

我觉得问题在于,你用来处理接收到的数据的线程,在请求还没来得及处理之前就已经关闭了。

比如说,如果你加上一个

thread1.join()

你的客户端看起来就会像这样

    def handle(self):
        thread1 = MyServerThread(self.request, self.client_address)
        thread1.start()
        thread1.join()

这样你就不会遇到错误了。

实际上,在调用处理函数后,处理器就关闭了连接。而你的问题是,线程在连接关闭之后还想去处理数据。

希望我能帮到你,我的英语不太好,希望你能理解(我来自法国)。

1

我觉得你在找的是 ThreadingMixIn

from SocketServer import TCPServer, ThreadingMixIn

class MyServerThread(ThreadingMixIn, TCPServer): pass

撰写回答