繁体   English   中英

客户端(1)到Python 3.x中的服务器到客户端(2)(套接字?)

[英]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的后端口) )。 如果你不想在最前沿滑冰,那么有一些伟大的第三方选择,如twistedgevent 所有这些选项都具有比socketserver更高的学习曲线,但这只能通过更加灵活和强大的功能来实现。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM