TCP 服务器线程作为连接用户和 Unix 套接字之间的代理

35 阅读2分钟

我正在编写一个 Web 应用程序,需要将数据从服务器推送到已连接的客户端。这些数据可以从 Web 应用程序的任何其他脚本发送。例如,一个用户在服务器上进行了一些更改,其他用户应该收到有关此更改的通知。

huake_00152_.jpg 因此,我的想法是使用 Unix 套接字(基于用户#ID 的套接字路径)发送给对应用户的数据(Web 应用程序脚本将连接到此套接字并写入数据)。第二部分是 ThreadingTCPServer,它将接受用户连接并将数据从 Unix 套接字推送到通过 TCP 套接字连接的用户。

以下是工作流程:

  • 用户连接到 TCP 服务器;
  • Django 脚本打开 Unix 套接字并将数据写入其中;
  • TCP 服务器从 Unix 套接字读取数据并将其发送到与用户的打开连接。

我希望你能理解我的想法 :)

所以我这里有两个问题:

    1. 你对我的想法有什么看法?这是一个好的还是坏的解决方案?欢迎提出任何建议。
    1. 这是我的代码。
import socket
import netstring
import sys, os, os.path
import string
import time

class MyRequestHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        try:
            print "Connected:", self.client_address

            user = self.request.recv(1024).strip().split(":")[1]
            user = int(user)
            self.request.send('Welcome #%s' % user)

            self.usocket_path = '/tmp/u%s.sock' % user
            if os.path.exists(self.usocket_path):
                os.remove(self.usocket_path)

            self.usocket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
            self.usocket.bind(self.usocket_path)
            self.usocket.listen(1)

            while 1:
                usocket_conn, addr = self.usocket.accept()
                while 1:
                    data = usocket_conn.recv(1024)
                    if not data: break
                    self.request.send(data)
                    break
                usocket_conn.close()
                time.sleep(0.1)

        except KeyboardInterrupt:
            self.request.send('close')
            self.request.close()

myServer = SocketServer.ThreadingTCPServer(('', 8081), MyRequestHandler)
myServer.serve_forever()

我遇到了一个异常:

 File "server1.py", line 23, in handle
    self.usocket.listen(1)
  File "<string>", line 1, in listen
error: (102, 'Operation not supported on socket')

2、解决方案

我不建议使用 Unix 套接字。如果你的应用程序(有一天)变得很受欢迎或对任务至关重要,你将无法仅仅添加另一个服务器来增加可伸缩性或使其具有冗余性和故障安全性。

另一方面,如果你将数据放入 memcached 中(并使用用户的“数据集编号”作为单独的键),你就可以从多个服务器向 memcached 中放入数据并从多个服务器读取数据。如果用户断开连接然后再从其他服务器重新连接,你仍然可以为他获取数据。

你也可以使用数据库(使其更加故障安全),或者根据你的喜好使用数据库和 memcached 的混合,但我已经看到一个应用程序像你试图的那样使用 Unix 套接字,后来程序员后悔了。该表可以拥有 userid、data 和 timestamp 列,你还可以记住给定用户的最后一个时间戳。