[英]Client(1) to Server to Client(2) in Python 3.x (Sockets?)
我一直在处理一个项目,该项目涉及向公共服务器发送信息(以演示密钥交换方案如何工作),然后将其发送给特定客户端。 只有两个客户。
我希望能够在如何从客户端(1)获取信息到服务器方面朝着正确的方向前进,然后让服务器将该信息重定向到客户端(2)。 我有点搞砸了代码,对如何从服务器发送和接收信息感到满意,但我不知道(到目前为止大约2个小时的研究)如何区分客户端并将信息发送给特定客户端我当前的服务器代码(与python3文档几乎没有变化:
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
"""
The RequestHandler class for our server.
It is instantiated once per connection to the server, and must
override the handle() method to implement communication to the
client.
"""
def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
print("{} wrote:".format(self.client_address[0]))
print(self.data)
# just send back the same data, but upper-cased
self.request.sendall(self.data.upper())
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
# Create the server, binding to localhost on port 9999
server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
# Activate the server; this will keep running until you
# interrupt the program with Ctrl-C
server.serve_forever()
我的客户端代码(与python3文档几乎没有变化:
import socket
import time
data = "matt is ok"
def contactserver(data):
HOST, PORT = "localhost", 9999
# Create a socket (SOCK_STREAM means a TCP socket)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect to server and send data
sock.connect((HOST, PORT))
sock.sendall(bytes(data, "utf-8"))
# Receive data from the server and shut down
received = str(sock.recv(1024), "utf-8")
print("Sent: {}".format(data))
print("Received: {}".format(received))
return format(received)
while True:
k = contactserver('banana')
time.sleep(1)
print(k)
首先,基本的socketserver.TCPServer
甚至无法同时与两个客户端通信。 正如文档解释:
这四个类同步处理请求; 必须在下一个请求开始之前完成每个请求。
正如同一段落告诉您的那样,您可以通过使用分叉或线程混合来解决该问题。 这很简单。
但是有一个更大的问题。 线程socketserver
服务器服务器为每个连接的客户端创建一个单独的,完全独立的对象,并且无法在它们之间进行通信,甚至让它们相互了解。 所以,你可以做什么?
你总是可以自己构建它。 在某处放置某种共享数据,并在其上进行某种同步,并且所有线程可以以任何线程, socketserver
或其他方式相同的方式相互socketserver
。
对于您的设计, queue
具有我们需要的所有内容:客户端1可以在队列上put
消息(客户端2是否已经显示),客户端2可以get
同一队列中get
消息(如果消息还没有,则自动等待,并且全部自动同步。
最大的问题是:服务器如何知道谁是客户1以及谁是客户2? 除非您想根据地址和端口进行切换,或者添加某种“登录”机制,否则我能想到的唯一规则是,首先连接的是客户端1,连接第二个的是客户端2,以及之后连接的任何人谁在乎,他们不属于这里。 因此,我们可以使用一个带有Lock
的简单共享标志。
把它们放在一起:
class MyTCPHandler(socketserver.ThreadingMixIn, socketserver.BaseRequestHandler):
q = queue.queue()
got_first = False
got_first_lock = threading.Lock()
def handle_request(self):
with MyTCPHandler.got_first_lock:
if MyTCPHandler.got_first:
first = False
else:
first = True
MyTCPHandler.got_first = True
if first:
self.data = self.request.recv(1024).strip()
print("{} wrote:".format(self.client_address[0]))
print(self.data)
# just send back the same data, but upper-cased
self.request.sendall(self.data.upper())
# and also queue it up for client 2
MyTCPHandler.q.put(self.data)
else:
# get the message off the queue, waiting if necessary
self.data = MyTCPHandler.q.get()
self.request.sendall(self.data)
如果你想构建一个更复杂的聊天服务器,每个人都与每个人交谈...好吧,这会变得有点复杂,而且你的socketserver
甚至超出了预期的限制范围。
我建议(a)降低到较低级别并手动编写线程或多路复用服务器,或者(b)转到更高级别,更强大的框架,以便更轻松地处理相互依赖的客户端。
stdlib有一些用于编写服务器的替代方案,但除了asyncio
之外它们asyncio
- 这很不错,但不幸的是全新的(它需要3.4,仍处于测试阶段,或者可以安装为3.3的后端口) )。 如果你不想在最前沿滑冰,那么有一些伟大的第三方选择,如twisted
或gevent
。 所有这些选项都具有比socketserver
更高的学习曲线,但这只能通过更加灵活和强大的功能来实现。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.