Trước hết dự án Autobahn cung cấp triển khai mã nguồn mở giao thức truyền thông WAMP. WAMP cung cấp hai mẫu giao tiếp RPC (Gọi thủ tục từ xa) và PUBSUB (Xuất bản-Đăng ký). Vì vậy, trong trường hợp của bạn, nó là cần thiết để tìm ra mô hình nào phù hợp với nhu cầu của bạn.
RPC
Theo WAMP FAQ RPC RPC bao gồm ba Roles. Đó là:
Trong trường hợp của bạn, callee là máy chủ trong khi Caller (Client) gọi một phương pháp trên máy chủ. Đây là những gì dường như làm việc cho bạn. (Một giá trị trả lại có thể được gửi đến Callee/khách hàng). Các đại lý có trách nhiệm định tuyến và có thể được bỏ qua tại thời điểm này. Vì vậy, xem xét các mô hình trên có vẻ như không phù hợp cho vấn đề của bạn.
PubSub
Các mô hình thứ hai là PubSub.Mô hình này bao gồm ba vai trò (lấy từ WAMP FAQ PUBSUB):
- Publisher
- Subscriber
- Broker
Vì vậy, những gì xảy ra là, nhà xuất bản (Server) công bố các sự kiện để chủ đề. Người đăng ký (Khách hàng) có thể đăng ký một chủ đề của Nhà xuất bản. Khi sự kiện được xuất bản, Người đăng ký sẽ nhận được sự kiện bao gồm cả tải trọng. Điều đó có nghĩa là bạn có thể cung cấp chủ đề "Phát sóng" và cho phép tất cả khách hàng đăng ký chủ đề. Nếu được yêu cầu, bạn có thể gửi tin nhắn quảng bá tới tất cả khách hàng.
Sau đó, bạn phải giải quyết vấn đề gửi tin nhắn cho các khách hàng đơn lẻ (Người đăng ký). Theo tài liệu, chức năng xuất bản để xuất bản một chủ đề có tham số tùy chọn để cung cấp danh sách "Khách hàng" đủ điều kiện nhận sự kiện. WAMP Documentation (Class Publish)
-------- EDIT --------
Nó không phải là rõ ràng những gì là có nghĩa là bởi "ứng dụng bên ngoài" và trong ngôn ngữ gì nó được coi là bằng văn bản. Vấn đề giải thích của Tác giả có thể được giải quyết nếu ứng dụng bên ngoài được viết bằng python, JavaScript hoặc Cpp hoặc Ứng dụng Android bằng cách sử dụng khung công tác Autobahn với (WAMP).
Cung cấp Autobahn, như được đề cập trong câu hỏi, cũng là triển khai giao thức websocket. Một cách tiếp cận khác để giải quyết vấn đề có thể là bằng cách sử dụng Autobahn Websockets và cho "ứng dụng bên ngoài" một Websocket thực hiện sự lựa chọn. Autobahn cung cấp cho Python và các giải pháp Websocket Android. Tất nhiên có nhiều thư viện hoặc mô-đun Websocket hơn. Java Websocket library, Python Websocket Client module và nhiều hơn nữa ...
Vì vậy, hãy cho phép Websocket Server được triển khai bằng cách sử dụng khung Autobahn. Ứng dụng bên ngoài là một ứng dụng khách khác kết nối với máy chủ và gửi một chuỗi được xác định bắt đầu bằng "send_broadcast: PAYLOAD" và tải trọng được nối thêm. Trên máy chủ, bạn có thể kiểm tra thông báo cho chuỗi và nếu msg bắt đầu bằng "send_broadcast", bạn có thể gửi phát sóng tới tất cả các máy khách được kết nối. Nếu bạn muốn gửi tin nhắn đến chỉ một khách hàng, bạn có thể xác định một chuỗi khác như "send_to_single: IP: PAYLOAD" chẳng hạn. Việc triển khai máy chủ sau đó có thể có một nhánh khác để kiểm tra "send_to_single" và gọi một phương thức khác, có thể là "def send_to_single" ?, và chuyển một đối số khác cho ip của máy khách. Thay vì gửi cho tất cả các máy khách, như trong phương thức phát sóng, bạn chỉ có thể gửi thông điệp tới máy khách đã cho. Một cách khác cho giao thức truyền thông của bạn sẽ sử dụng JSON. bạn có thể xác định msg của bạn như sau:
{
"type": "broadcast",
"msg": "your_message"
}
hoặc
{
"type": "single",
"elegible": ["IP_1", "???"],
"msg": "your_message"
}
Trên Server thì bạn nạp Payload, kiểm tra các loại và làm các bước tiếp theo.
server
import sys
from twisted.internet import reactor
from twisted.python import log
from twisted.web.server import Site
from twisted.web.static import File
from autobahn.twisted.websocket import WebSocketServerFactory, \
WebSocketServerProtocol, \
listenWS
class BroadcastServerProtocol(WebSocketServerProtocol):
def onOpen(self):
self.factory.register(self)
def onConnect(self, request):
print("Client connecting: {}".format(request.peer))
def onMessage(self, payload, isBinary):
if not isBinary:
if "send_broadcast" in payload.decode('utf8'):
msg = "Send broadcast was ordered"
self.factory.broadcast(msg)
def connectionLost(self, reason):
WebSocketServerProtocol.connectionLost(self, reason)
self.factory.unregister(self)
class BroadcastServerFactory(WebSocketServerFactory):
"""
Simple broadcast server broadcasting any message it receives to all
currently connected clients.
"""
def __init__(self, url, debug=False, debugCodePaths=False):
WebSocketServerFactory.__init__(self, url, debug=debug, debugCodePaths=debugCodePaths)
self.clients = []
self.tickcount = 0
self.tick()
def tick(self):
self.tickcount += 1
self.broadcast("tick %d from server" % self.tickcount)
reactor.callLater(1, self.tick)
def register(self, client):
if client not in self.clients:
print("registered client {}".format(client.peer))
self.clients.append(client)
def unregister(self, client):
if client in self.clients:
print("unregistered client {}".format(client.peer))
self.clients.remove(client)
def broadcast(self, msg):
print("broadcasting message '{}' ..".format(msg))
for c in self.clients:
c.sendMessage(msg.encode('utf8'))
print("message sent to {}".format(c.peer))
class BroadcastPreparedServerFactory(BroadcastServerFactory):
"""
Functionally same as above, but optimized broadcast using
prepareMessage and sendPreparedMessage.
"""
def broadcast(self, msg):
print("broadcasting prepared message '{}' ..".format(msg))
preparedMsg = self.prepareMessage(msg)
for c in self.clients:
c.sendPreparedMessage(preparedMsg)
print("prepared message sent to {}".format(c.peer))
if __name__ == '__main__':
if len(sys.argv) > 1 and sys.argv[1] == 'debug':
log.startLogging(sys.stdout)
debug = True
else:
debug = False
ServerFactory = BroadcastServerFactory
# ServerFactory = BroadcastPreparedServerFactory
factory = ServerFactory("ws://localhost:9000",
debug=debug,
debugCodePaths=debug)
factory.protocol = BroadcastServerProtocol
factory.setProtocolOptions(allowHixie76=True)
listenWS(factory)
webdir = File(".")
web = Site(webdir)
reactor.listenTCP(8080, web)
reactor.run()
Khách hàng Client được viết cũng bằng Python sử dụng một khác nhau thực hiện mô-đun và vẫn hoạt động.Tất nhiên là cần thiết để liên lạc với một Websocket Server bằng giao thức Websocket.
from websocket import create_connection
ws = create_connection("ws://localhost:9000")
print "Sending 'send_broadcast'..."
ws.send("send_broadcast:PAYLOAD")
print "Sent"
print "Reeiving..." # OPTIONAL
result = ws.recv() # OPTIONAL
print "Received '%s'" % result # OPTIONAL
ws.close(
)
Câu hỏi đặt ra chưa được trả lời mặc dù. Ví dụ trên KHÔNG phát các tin nhắn từ một nguồn bên ngoài, chúng chỉ sử dụng một giấc ngủ để phát một tin nhắn nội bộ sau mỗi 5 giây. – someuser
Vì vậy, hãy giải thích về nguồn bên ngoài của bạn. Điện thoại thông minh (IOS/Android) hoặc trình duyệt? Hoặc một máy tính/máy tính xách tay? – Ben
Vâng, tôi đã chỉnh sửa câu trả lời của tôi, đưa ra một gợi ý về cách kết nối với máy chủ và yêu cầu máy chủ gửi một chương trình phát sóng hoặc tin nhắn tới một khách hàng. Nó không bao gồm thông điệp khách duy nhất nhưng giải thích cách nó có thể được quản lý. Câu hỏi đặt ra là đi đúng hướng. Tôi hy vọng câu trả lời sẽ giúp bạn biết được nơi để đi từ đây. – Ben