我想创建一个服务器,它可以同时处理多个客户机(处理:同时从客户机接收数据并向所有客户机发送数据!!!)在
实际上,我正在尝试创建一个聊天框。程序的工作原理如下:
1)将有一个服务器来处理客户机。在
2)多个客户端可以加入服务器。在
3)客户端向服务器发送消息(字符串)。在
4)服务器接收来自客户端的消息,然后将其发送给所有人 除了从他那里得到的客户。在
这就是客户之间的沟通方式。没有可用的私人消息。当有人按enter键时,所有客户机都会在屏幕上看到消息。在
客户机模块很容易制作,因为客户机只与一个套接字(服务器)通信。在
另一方面,服务器模块非常复杂,我不知道怎么做(我也知道线程)。在
这是我的请求:
import socket, threading
class Server:
def __init__(self, ip = "", port = 5050):
'''Server Constructor. If __init__ return None, then you can use
self.error to print the specified error message.'''
#Error message.
self.error = ""
#Creating a socket object.
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#Trying to bind it.
try:
self.server.bind( (ip, port) )
pass
#Failed, because socket has been shuted down.
except OSError :
self.error = "The server socket has been shuted down."
return None
#Failed, because socket has been forcibly reseted.
except ConnectionResetError:
self.error = "The server socket has been forcibly reseted."
return None
#Start Listening.
self.server.listen()
#_____Other Variables_____#
#A flag to know when to shut down thread loops.
self.running = True
#Store clients here.
self.clients = []
#_____Other Variables_____#
#Start accepting clients.
thread = threading.thread(target = self.acceptClients)
thread.start()
#Start handling the client.
self.clientHandler()
#Accept Clients.
def acceptClients(self):
while self.running:
self.clients.append( self.server.accept() )
#Close the server.
self.server.close()
#Handle clients.
def clientHandler(self):
while self.running:
for client in self.clients:
sock = client[0]
addr = client[1]
#Receive at most 1 mb of data.
#The problem is that recv will block the loop!!!
data = sock.recv(1024 ** 2)
如您所见,我接受使用线程的客户机,因此服务器.接受()不会阻止程序。然后我把客户存储到一个列表中。在
但问题出在clientHandler上。我怎么才能从所有人那里收到 同时有客户吗?第一次接收将阻止循环!!!在
我还尝试为每个新客户机启动新线程(clientandler) 但问题是同步。在
那送信呢?服务器必须向所有客户机发送数据,因此clientHandler尚未完成。但是如果我混合使用recv和send方法,那么问题就变得更复杂了。在
那么,怎样做才是正确和最好的方法呢? 我也想给我举个例子。在
当不同的客户机彼此独立时,多线程处理是很好的:您编写代码时就好像只有一个客户机,然后为每个客户机启动一个线程。在
但是在这里,来自一个客户的信息必须发送给其他客户。每个客户端一个线程肯定会导致同步噩梦。所以让我们呼叫
select
去营救!select.select
允许轮询套接字列表,并在套接字就绪后立即返回。在这里,您只需构建一个包含侦听套接字和所有可接受套接字的列表(该部分最初为空…):代码可以是(或多或少):
您当然需要实现一种机制来要求服务器停止,并测试所有这些,但这应该是一个起点
这是我的最后一个节目,很有魅力。
服务器.py
导入套接字,选择
类服务器:
客户端.py
导入插座,螺纹
来自tkinter import*
类客户:
^{pr2}$程序运行良好,完全符合我的要求。在
但我还有一些问题。在
r,w,x=选择。选择(自插座, [], 自插座)
r是一个包含所有就绪套接字的列表。 但我并没有忘记什么是w和x。在
第一个参数是套接字列表,第二个是接受的客户端 第三个参数是什么?为什么我要再次给出套接字列表?在
相关问题 更多 >
编程相关推荐