[英]Multi-threaded multi-client server in python
我正在python中编写一个多线程,多客户端服务器。 多个用户可以使用telnet连接到它,并基本上将其用作聊天服务器。 我可以通过telnet连接两个客户端,但我遇到了以下两个问题:
服务器代码:
import os
import sys
import socket
import thread
port = 1941
global message
global lock
global file
def handler(connection):
while 1:
file = connection.makefile()
file.flush()
temp = file.readline()
if temp == 'quit':
break
lock.acquire()
message += temp
lock.release()
file.write(message)
file.close()
acceptor = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
acceptor.bind(('', port))
acceptor.listen(10)
lock = thread.allocate_lock()
while 1:
connection, addr = acceptor.accept()
thread.start_new_thread(handler, (connection,))
好的,我听了unholysampler,现在我有了这个。 我现在能够与两个客户端连接并输入消息,但它们没有被发送/接收(我无法分辨哪一个)。
import os
import sys
import socket
import thread
port = 1953
def handler(connection):
global message
global filelist
filelist = []
file = connection.makefile()
file.flush()
filelist.append(file)
message = ''
while 1:
i = 0
while i < (len(filelist)):
filelist[i].flush()
temp = filelist[i].readline()
if temp == 'quit':
break
with lock:
message += temp
i = i + 1
file.close()
global lock
acceptor = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
acceptor.bind(('', port))
acceptor.listen(10)
lock = thread.allocate_lock()
while 1:
connection, addr = acceptor.accept()
thread.start_new_thread(handler, (connection,))
使用Twisted实现这种事情要简单得多,它可以让你在一个线程中同时处理多个客户端,并提供更好的API。
以下是使用Twisted编写聊天服务器的方法( chatserver.py中的完整示例):
class MyChat(basic.LineReceiver):
def connectionMade(self):
print "Got new client!"
self.factory.clients.append(self)
def connectionLost(self, reason):
print "Lost a client!"
self.factory.clients.remove(self)
def lineReceived(self, line):
print "received", repr(line)
for c in self.factory.clients:
c.message(line)
def message(self, message):
self.transport.write(message + '\n')
对于每个用户,创建一个MyChat
对象,并且事件循环调用其启动/停止事件的方法以及从客户端收到一行时。 在这种情况下,它只是将它接收的每一行发送给系统中的所有客户端。 由于它在单个线程中运行,因此不需要锁定。
这不是你如何使用global
。 在方法范围内定义方法时,可以使用global命令将变量引用为更高范围的变量。
message = 1
def globalTest():
global message
message += 1
print message
print message
globalTest()
print message
每次迭代循环时,您都要为连接创建一个新的文件对象。 你想在循环开始之前做到这一点,所以你只做了一次。
您正在读取和写入同一文件对象。 这意味着它只是一个echo服务器。 你永远不会给thread1一个对thread2文件的引用。 尝试为套接字文件使用一个全局变量将不起作用,因为您永远不会知道它实际指向哪个套接字。 (问题#2)
您永远不会初始化消息,因此message += temp
将抛出一个UnboudLocalError
表示在分配值之前它已被引用。 (可能是问题#1的原因)另外,为什么要首先附加字符串,这意味着每次发送内容时,都会发送整个会话。
此外,不要手动获取和释放锁,使用更清洁。
with lock:
message += temp
我想你需要在每个连接之前调用s.listen。 这是把它放在无限循环中。 while True: acceptor.listen(1) #...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.