Python 中的多线程 TCP 服务器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17453212/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Multi Threaded TCP server in Python
提问by Deepal
I have created a simple multi threaded tcp server using python's threding module. This server creates a new thread each time a new client is connected.
我使用python的线程模块创建了一个简单的多线程tcp服务器。每次连接新客户端时,此服务器都会创建一个新线程。
#!/usr/bin/env python
import socket, threading
class ClientThread(threading.Thread):
def __init__(self,ip,port):
threading.Thread.__init__(self)
self.ip = ip
self.port = port
print "[+] New thread started for "+ip+":"+str(port)
def run(self):
print "Connection from : "+ip+":"+str(port)
clientsock.send("\nWelcome to the server\n\n")
data = "dummydata"
while len(data):
data = clientsock.recv(2048)
print "Client sent : "+data
clientsock.send("You sent me : "+data)
print "Client disconnected..."
host = "0.0.0.0"
port = 9999
tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpsock.bind((host,port))
threads = []
while True:
tcpsock.listen(4)
print "\nListening for incoming connections..."
(clientsock, (ip, port)) = tcpsock.accept()
newthread = ClientThread(ip, port)
newthread.start()
threads.append(newthread)
for t in threads:
t.join()
Then I opened two new terminals and connected to the server using netcat. Then, when I type and send my first data to the server using the first terminal I connected, reply from the server comes to the other terminal and first connection got disconnected. I guessed the reason but I am doubtful whether this happens because clientsockvariable is overwritten so that it refers to the second connection's socket. Am I correct and then how to avoid that?
然后我打开了两个新终端并使用netcat连接到服务器。然后,当我使用我连接的第一个终端输入我的第一个数据并将其发送到服务器时,来自服务器的回复到达另一个终端并且第一个连接断开。我猜到了原因,但我怀疑这是否会发生,因为clientsock变量被覆盖,因此它指的是第二个连接的套接字。我是否正确,然后如何避免这种情况?
Is there a way other than using an array with limited number of socket variables and using each variable for each connection?
除了使用套接字变量数量有限的数组并为每个连接使用每个变量之外,还有其他方法吗?
采纳答案by mata
You should pass the client sock to the thread like you do with the ip address and the port:
您应该像处理 IP 地址和端口一样将客户端 sock 传递给线程:
class ClientThread(threading.Thread):
def __init__(self, ip, port, socket):
threading.Thread.__init__(self)
self.ip = ip
self.port = port
self.socket = socket
print "[+] New thread started for "+ip+":"+str(port)
def run(self):
# use self.socket to send/receive
...
(clientsock, (ip, port)) = tcpsock.accept()
newthread = ClientThread(ip, port, clientsock)
...
回答by arbel03
I have created this nice class you can override
我创建了这个不错的类,您可以覆盖
import socket
import thread
class SocketServer(socket.socket):
clients = []
def __init__(self):
socket.socket.__init__(self)
#To silence- address occupied!!
self.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.bind(('0.0.0.0', 8080))
self.listen(5)
def run(self):
print "Server started"
try:
self.accept_clients()
except Exception as ex:
print ex
finally:
print "Server closed"
for client in self.clients:
client.close()
self.close()
def accept_clients(self):
while 1:
(clientsocket, address) = self.accept()
#Adding client to clients list
self.clients.append(clientsocket)
#Client Connected
self.onopen(clientsocket)
#Receiving data from client
thread.start_new_thread(self.recieve, (clientsocket,))
def recieve(self, client):
while 1:
data = client.recv(1024)
if data == '':
break
#Message Received
self.onmessage(client, data)
#Removing client from clients list
self.clients.remove(client)
#Client Disconnected
self.onclose(client)
#Closing connection with client
client.close()
#Closing thread
thread.exit()
print self.clients
def broadcast(self, message):
#Sending message to all clients
for client in self.clients:
client.send(message)
def onopen(self, client):
pass
def onmessage(self, client, message):
pass
def onclose(self, client):
pass
And here's an example:
这是一个例子:
class BasicChatServer(SocketServer):
def __init__(self):
SocketServer.__init__(self)
def onmessage(self, client, message):
print "Client Sent Message"
#Sending message to all clients
self.broadcast(message)
def onopen(self, client):
print "Client Connected"
def onclose(self, client):
print "Client Disconnected"
def main():
server = BasicChatServer()
server.run()
if __name__ == "__main__":
main()