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,))
I'm writing a multi-threaded, multi-client server in python. Multiple users can connect to it with telnet and basically use it as a chat server. I'm able to connect with two clients through telnet, but I run into the two following problems:
- The first client to send a message is immediately disconnected.
- The other client does not the receive the message sent by the first client.
Server code:
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,))
Ok I listened to unholysampler and now I have this. I'm able to to connect with both clients now and type messages, but they aren't being sent/received (I can't tell which one).
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,))
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
使用 Twisted 实现此类事情要简单得多,效果更好,它允许您在单个线程中同时处理多个客户端,以及提供更好的 API。
以下是如何使用 Twisted 编写聊天服务器(完整示例位于 聊天服务器中。 py):
对于每个用户,都会创建一个
MyChat
对象,事件循环会在开始/停止事件以及从客户端收到一行时调用其方法。在这种情况下,它只是将收到的每一行发送给系统中的所有客户端。由于它在单线程中运行,因此不需要锁。It's much simpler and better to implement this sort of thing using Twisted, which lets you handle multiple clients concurrently in a single thread, as well as providing a nicer API.
Here's how you write a chat server using Twisted (full example in chatserver.py):
For each user, a
MyChat
object gets created, and the event loop calls its methods for start/stop events and when a line is received from the client. In this case, it just send every line it receives to all the clients in the system. Since it runs in a single thread, no locks are needed.这不是您使用
global
的方式。当您在方法作用域内定义方法时,可以使用全局命令来引用更高作用域的变量。每次迭代循环时,您都会为连接创建一个新的文件对象。您想在循环开始之前进行此操作,因此只需执行一次。
您正在读取和写入同一个文件对象。这意味着它只是一个回显服务器。您永远不会向 thread1 提供对 thread2 文件的引用。尝试对套接字文件使用一个全局变量是行不通的,因为您永远不知道它实际上指向哪个套接字。 (问题#2)
您从不初始化消息,因此
message += temp
将抛出一个UnboudLocalError
,表示在赋值之前它已被引用。 (可能是问题 #1 的原因)另外,为什么要首先附加字符串,这意味着每次发送内容时,整个对话都会发送出去。另外,不要手动获取和释放锁,使用 with 更干净。
That's not how you use
global
. When you define a method, inside the method scope, you use the global command to make references to the variable the the higher scoped variable.You are making a new file object for the connection every time you iterate over the loop. You want to make that before the loop starts so you are only doing it once.
You are reading from and writing to the same file object. This means it is just an echo server. You are never giving thread1 a reference to thread2's file. Trying to use one global variable for the socket file will not work because you will never know which socket it is actually pointing to. (Issue #2)
You never initialize message, so
message += temp
will throw anUnboudLocalError
saying that it is being referenced before assigned a value. (Likely the cause of issue #1) Also, why are you appending the string in the first place, that means every time something is sent, the entire conversation is sent out.Also, don't manually acquire and release the lock, using with is cleaner.
我认为你需要在每次连接之前调用 s.listen 。也就是将其放入无限循环中。
当为真时:
接受器.listen(1)
#...
I think you need to call s.listen before every single connection. That is put it inside the infinite loop.
while True:
acceptor.listen(1)
#...