我正在用Python编写多线程套接字应用程序。
以下是我所拥有的基本框架代码:
import socket, threading, time
class listener:
def __init__(self):
# Create a local listener socket
self.socket = socket.socket(AF_INET, SOCK_STREAM)
# Set options
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
def start(self):
# Start listening for incoming connections in a loop. As connections
# come in, start new threads and accept/work with them.
self.socket.bind(('',1001)) # Bind to all addresses
while (True):
self.socket.listen(1) # blocks until a new connection is available
newSocket, addr = self.socket.accept() # Accept connection
thisConnThread = threading.Thread(target=server().runServer, args=( newSocket, addr ) )
thisConnThread.start() # call the connection handler on a new thread
# now return and listen for more connections.
class server:
def RunServer(self, socket, addr):
socket.write("Hello world!\n")
# Create a thread to listen for input from the client
thisListenThread = threading.Thread(target=self.RunServer_Listener, args=(socket.) )
thisListenThread.start()
# To demonstrate async - print a value every so many seconds - this
# needs to happen separately from the listener.
for i in range(0,100):
socket.write("Checkpoint!\n")
time.sleep(60)
socket.write("Your time is UP! Bye!\n")
socket.shutdown(socket.SHUTDOWN_RDWR) # close the connection
def RunServer_Listener(self, socket):
while (True):
inData = socket.read(4096) # blocks until data arrives
if not inData:
break # connection must be closed
socket.write("You wrote: %s\n" % inData)
在这种情况下,我期望发生的是每次连接进入时,都会创建一个新的server
实例,并生成一个新的线程来运行它。
换句话说,对我来说,thisConnThread = threading.Thread(target=server().runServer, args=( newSocket, addr ) )
行应该创建server
的新实例,然后执行其中包含的函数。
我设置了一个单独的侦听器线程,因为在实际的服务器上,服务器可能需要随时向客户端发送数据,但它也需要随时响应客户端。由于read()阻塞直到数据可用,因此创建一个等待来自客户端的输入然后处理它的侦听线程是有意义的,但主连接线程仍然可以执行它需要做的事情并写入客户端独立于听众。
如果我与此服务器有一个连接,则此操作完全符合预期。
但是,如果我将第二个客户端连接到服务器,则会发生奇怪的事情。最重要和最关注的是,如果我键入第二个实例的客户端,有时回复将转到第二个实例,有时转到FIRST实例,反之亦然。这几乎就像write()操作正在做某种循环的事情 - 它交替地进入每个实例。
对于本练习,实际上不需要保持活动连接列表。这可能是为了一个以后或更高级的项目,但是现在,客户只是在服务器上度过他们的时间,然后离开,服务器没有任何理由与其他连接进行交互。
我确定我在这里遗漏了一些东西,也许我的线程实现是错误的,或者我使用套接字是完全错误的。无论哪种方式,是否有人就如何完全独立于服务器的连接提出一些建议?
答案 0 :(得分:1)
在做了一堆或多或少明显的修复之后,你的代码在Python 2.7中似乎对我很好。这是补丁(注意,我也更改了端口号,加快了超时等)。
(未添加适当的join
或setDaemon
来电,似乎不值得这样做。)
diff --git a/fdmillion.py b/fdmillion.py
index 8109c83..1362d3d 100644
--- a/fdmillion.py
+++ b/fdmillion.py
@@ -1,40 +1,44 @@
import socket, threading, time
+from socket import AF_INET, SOCK_STREAM
class listener:
def __init__(self):
# Create a local listener socket
- self.socket = socket.socket(AF_INET, SOCK_STREAM)
+ self.sock = socket.socket(AF_INET, SOCK_STREAM)
# Set options
- self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
def start(self):
# Start listening for incoming connections in a loop. As connections
# come in, start new threads and accept/work with them.
- self.socket.bind(('',1001)) # Bind to all addresses
+ self.sock.bind(('',8001)) # Bind to all addresses
while (True):
- self.socket.listen(1) # blocks until a new connection is available
- newSocket, addr = self.socket.accept() # Accept connection
- thisConnThread = threading.Thread(target=server().runServer, args=( newSocket, addr ) )
+ self.sock.listen(1) # blocks until a new connection is available
+ newSocket, addr = self.sock.accept() # Accept connection
+ thisConnThread = threading.Thread(target=server().RunServer, args=( newSocket, addr ) )
thisConnThread.start() # call the connection handler on a new thread
# now return and listen for more connections.
class server:
- def RunServer(self, socket, addr):
- socket.write("Hello world!\n")
+ def RunServer(self, sock, addr):
+ sock.sendall("Hello world!\n")
# Create a thread to listen for input from the client
- thisListenThread = threading.Thread(target=self.RunServer_Listener, args=(socket.) )
+ thisListenThread = threading.Thread(target=self.RunServer_Listener, args=(sock,) )
thisListenThread.start()
# To demonstrate async - print a value every so many seconds - this
# needs to happen separately from the listener.
- for i in range(0,100):
- socket.write("Checkpoint!\n")
- time.sleep(60)
- socket.write("Your time is UP! Bye!\n")
- socket.shutdown(socket.SHUTDOWN_RDWR) # close the connection
+ for i in range(5,0,-1):
+ sock.sendall("Checkpoint! %d...\n" % i)
+ time.sleep(5)
+ sock.sendall("Your time is UP! Bye!\n")
+ sock.shutdown(socket.SHUT_RDWR) # close the connection
- def RunServer_Listener(self, socket):
+ def RunServer_Listener(self, sock):
while (True):
- inData = socket.read(4096) # blocks until data arrives
+ inData = sock.recv(4096) # blocks until data arrives
if not inData:
break # connection must be closed
- socket.write("You wrote: %s\n" % inData)
+ sock.sendall("You wrote: %s\n" % inData)
+
+if __name__ == '__main__':
+ listener().start()
[编辑以修复通过less
]