socket.d 2.4.10__tar.gz → 2.4.10.2__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. {socket.d-2.4.10 → socket.d-2.4.10.2}/PKG-INFO +1 -1
  2. socket.d-2.4.10.2/README.md +42 -0
  3. {socket.d-2.4.10 → socket.d-2.4.10.2}/setup.py +2 -2
  4. {socket.d-2.4.10 → socket.d-2.4.10.2}/socket.d.egg-info/PKG-INFO +1 -1
  5. socket.d-2.4.10.2/socket.d.egg-info/SOURCES.txt +125 -0
  6. socket.d-2.4.10.2/socketd/broker/BrokerFragmentHandler.py +7 -0
  7. socket.d-2.4.10.2/socketd/broker/BrokerListener.py +93 -0
  8. socket.d-2.4.10.2/socketd/broker/BrokerListenerBase.py +82 -0
  9. socket.d-2.4.10.2/socketd/broker/__init__.py +0 -0
  10. socket.d-2.4.10.2/socketd/cluster/ClusterClient.py +75 -0
  11. socket.d-2.4.10.2/socketd/cluster/ClusterClientSession.py +80 -0
  12. socket.d-2.4.10.2/socketd/cluster/LoadBalancer.py +65 -0
  13. socket.d-2.4.10.2/socketd/cluster/__init__.py +0 -0
  14. socket.d-2.4.10.2/socketd/exception/SocketDExecption.py +38 -0
  15. socket.d-2.4.10.2/socketd/exception/__init__.py +0 -0
  16. socket.d-2.4.10.2/socketd/transport/__init__.py +0 -0
  17. socket.d-2.4.10.2/socketd/transport/client/Client.py +57 -0
  18. socket.d-2.4.10.2/socketd/transport/client/ClientBase.py +97 -0
  19. socket.d-2.4.10.2/socketd/transport/client/ClientChannel.py +192 -0
  20. socket.d-2.4.10.2/socketd/transport/client/ClientConfig.py +96 -0
  21. socket.d-2.4.10.2/socketd/transport/client/ClientConfigHandler.py +4 -0
  22. socket.d-2.4.10.2/socketd/transport/client/ClientConnectHandler.py +10 -0
  23. socket.d-2.4.10.2/socketd/transport/client/ClientConnector.py +23 -0
  24. socket.d-2.4.10.2/socketd/transport/client/ClientConnectorBase.py +20 -0
  25. socket.d-2.4.10.2/socketd/transport/client/ClientHandshakeResult.py +15 -0
  26. socket.d-2.4.10.2/socketd/transport/client/ClientHeartbeatHandler.py +10 -0
  27. socket.d-2.4.10.2/socketd/transport/client/ClientProvider.py +15 -0
  28. socket.d-2.4.10.2/socketd/transport/client/ClientSession.py +48 -0
  29. socket.d-2.4.10.2/socketd/transport/client/__init__.py +0 -0
  30. socket.d-2.4.10.2/socketd/transport/core/Asserts.py +35 -0
  31. socket.d-2.4.10.2/socketd/transport/core/Channel.py +112 -0
  32. socket.d-2.4.10.2/socketd/transport/core/ChannelAssistant.py +31 -0
  33. socket.d-2.4.10.2/socketd/transport/core/ChannelInternal.py +24 -0
  34. socket.d-2.4.10.2/socketd/transport/core/ChannelSupporter.py +21 -0
  35. socket.d-2.4.10.2/socketd/transport/core/Codec.py +72 -0
  36. socket.d-2.4.10.2/socketd/transport/core/Config.py +142 -0
  37. socket.d-2.4.10.2/socketd/transport/core/Costants.py +52 -0
  38. socket.d-2.4.10.2/socketd/transport/core/Entity.py +50 -0
  39. socket.d-2.4.10.2/socketd/transport/core/EntityMetas.py +22 -0
  40. socket.d-2.4.10.2/socketd/transport/core/Flags.py +74 -0
  41. socket.d-2.4.10.2/socketd/transport/core/FragmentAggregator.py +58 -0
  42. socket.d-2.4.10.2/socketd/transport/core/FragmentHandler.py +31 -0
  43. socket.d-2.4.10.2/socketd/transport/core/Frame.py +18 -0
  44. socket.d-2.4.10.2/socketd/transport/core/Frames.py +63 -0
  45. socket.d-2.4.10.2/socketd/transport/core/HandshakeDefault.py +92 -0
  46. socket.d-2.4.10.2/socketd/transport/core/IdGenerator.py +9 -0
  47. socket.d-2.4.10.2/socketd/transport/core/Listener.py +22 -0
  48. socket.d-2.4.10.2/socketd/transport/core/Message.py +37 -0
  49. socket.d-2.4.10.2/socketd/transport/core/Processor.py +33 -0
  50. socket.d-2.4.10.2/socketd/transport/core/Session.py +85 -0
  51. socket.d-2.4.10.2/socketd/transport/core/__init__.py +0 -0
  52. socket.d-2.4.10.2/socketd/transport/core/codec/Buffer.py +42 -0
  53. socket.d-2.4.10.2/socketd/transport/core/codec/ByteBufferCodecReader.py +33 -0
  54. socket.d-2.4.10.2/socketd/transport/core/codec/ByteBufferCodecWriter.py +24 -0
  55. socket.d-2.4.10.2/socketd/transport/core/codec/CodecDefault.py +116 -0
  56. socket.d-2.4.10.2/socketd/transport/core/codec/__init__.py +9 -0
  57. socket.d-2.4.10.2/socketd/transport/core/entity/EntityDefault.py +126 -0
  58. socket.d-2.4.10.2/socketd/transport/core/entity/FileEntity.py +28 -0
  59. socket.d-2.4.10.2/socketd/transport/core/entity/MessageBuilder.py +33 -0
  60. socket.d-2.4.10.2/socketd/transport/core/entity/MessageDefault.py +81 -0
  61. socket.d-2.4.10.2/socketd/transport/core/entity/StringEntity.py +10 -0
  62. socket.d-2.4.10.2/socketd/transport/core/entity/__init__.py +0 -0
  63. socket.d-2.4.10.2/socketd/transport/core/fragment/FragmentAggregatorDefault.py +56 -0
  64. socket.d-2.4.10.2/socketd/transport/core/fragment/FragmentHandlerBase.py +73 -0
  65. socket.d-2.4.10.2/socketd/transport/core/fragment/FragmentHandlerDefault.py +15 -0
  66. socket.d-2.4.10.2/socketd/transport/core/fragment/FragmentHolder.py +8 -0
  67. socket.d-2.4.10.2/socketd/transport/core/fragment/__init__.py +0 -0
  68. socket.d-2.4.10.2/socketd/transport/core/impl/ChannelBase.py +80 -0
  69. socket.d-2.4.10.2/socketd/transport/core/impl/ChannelDefault.py +172 -0
  70. socket.d-2.4.10.2/socketd/transport/core/impl/ConfigBase.py +218 -0
  71. socket.d-2.4.10.2/socketd/transport/core/impl/LogConfig.py +11 -0
  72. socket.d-2.4.10.2/socketd/transport/core/impl/ProcessorDefault.py +181 -0
  73. socket.d-2.4.10.2/socketd/transport/core/impl/SessionBase.py +51 -0
  74. socket.d-2.4.10.2/socketd/transport/core/impl/SessionDefault.py +111 -0
  75. socket.d-2.4.10.2/socketd/transport/core/impl/__init__.py +0 -0
  76. socket.d-2.4.10.2/socketd/transport/core/listener/EventListener.py +57 -0
  77. socket.d-2.4.10.2/socketd/transport/core/listener/PathListener.py +32 -0
  78. socket.d-2.4.10.2/socketd/transport/core/listener/PathMapper.py +11 -0
  79. socket.d-2.4.10.2/socketd/transport/core/listener/PipelineListener.py +21 -0
  80. socket.d-2.4.10.2/socketd/transport/core/listener/SimpleListener.py +18 -0
  81. socket.d-2.4.10.2/socketd/transport/core/listener/__init__.py +0 -0
  82. socket.d-2.4.10.2/socketd/transport/server/Server.py +24 -0
  83. socket.d-2.4.10.2/socketd/transport/server/ServerBase.py +86 -0
  84. socket.d-2.4.10.2/socketd/transport/server/ServerConfig.py +53 -0
  85. socket.d-2.4.10.2/socketd/transport/server/ServerProvider.py +9 -0
  86. socket.d-2.4.10.2/socketd/transport/server/__init__.py +0 -0
  87. socket.d-2.4.10.2/socketd/transport/stream/RequestStream.py +36 -0
  88. socket.d-2.4.10.2/socketd/transport/stream/SendStream.py +14 -0
  89. socket.d-2.4.10.2/socketd/transport/stream/Stream.py +32 -0
  90. socket.d-2.4.10.2/socketd/transport/stream/StreamBase.py +62 -0
  91. socket.d-2.4.10.2/socketd/transport/stream/StreamManger.py +41 -0
  92. socket.d-2.4.10.2/socketd/transport/stream/StreamMangerDefault.py +32 -0
  93. socket.d-2.4.10.2/socketd/transport/stream/SubscribeStream.py +28 -0
  94. socket.d-2.4.10.2/socketd/transport/stream/__init__.py +0 -0
  95. socket.d-2.4.10.2/socketd/transport/utils/AsyncUtil.py +100 -0
  96. socket.d-2.4.10.2/socketd/transport/utils/CompletableFuture.py +63 -0
  97. socket.d-2.4.10.2/socketd/transport/utils/StrUtil.py +26 -0
  98. socket.d-2.4.10.2/socketd/transport/utils/__init__.py +0 -0
  99. socket.d-2.4.10.2/socketd/transport/utils/async_api/AtomicRefer.py +36 -0
  100. socket.d-2.4.10.2/socketd/transport/utils/async_api/__init__.py +0 -0
  101. socket.d-2.4.10.2/socketd/transport/utils/sync_api/AtomicRefer.py +36 -0
  102. socket.d-2.4.10.2/socketd/transport/utils/sync_api/__init__.py +0 -0
  103. socket.d-2.4.10.2/socketd_websocket/impl/AIOConnect.py +121 -0
  104. socket.d-2.4.10.2/socketd_websocket/impl/AIOServe.py +151 -0
  105. socket.d-2.4.10.2/socketd_websocket/impl/AIOWebSocketClientImpl.py +135 -0
  106. socket.d-2.4.10.2/socketd_websocket/impl/AIOWebSocketServerImpl.py +111 -0
  107. socket.d-2.4.10.2/socketd_websocket/impl/__init__.py +6 -0
  108. socket.d-2.4.10/README.md +0 -10
  109. socket.d-2.4.10/socket.d.egg-info/SOURCES.txt +0 -23
  110. {socket.d-2.4.10 → socket.d-2.4.10.2}/setup.cfg +0 -0
  111. {socket.d-2.4.10 → socket.d-2.4.10.2}/socket.d.egg-info/dependency_links.txt +0 -0
  112. {socket.d-2.4.10 → socket.d-2.4.10.2}/socket.d.egg-info/requires.txt +0 -0
  113. {socket.d-2.4.10 → socket.d-2.4.10.2}/socket.d.egg-info/top_level.txt +0 -0
  114. {socket.d-2.4.10 → socket.d-2.4.10.2}/socket.d.egg-info/zip-safe +0 -0
  115. {socket.d-2.4.10 → socket.d-2.4.10.2}/socketd/SocketD.py +0 -0
  116. {socket.d-2.4.10 → socket.d-2.4.10.2}/socketd/__init__.py +0 -0
  117. {socket.d-2.4.10 → socket.d-2.4.10.2}/socketd_aio_tcp/TCPAIOServer.py +0 -0
  118. {socket.d-2.4.10 → socket.d-2.4.10.2}/socketd_aio_tcp/TCPStreamIO.py +0 -0
  119. {socket.d-2.4.10 → socket.d-2.4.10.2}/socketd_aio_tcp/TcpAIOChannelAssistant.py +0 -0
  120. {socket.d-2.4.10 → socket.d-2.4.10.2}/socketd_aio_tcp/TcpAioClient.py +0 -0
  121. {socket.d-2.4.10 → socket.d-2.4.10.2}/socketd_aio_tcp/TcpAioClientConnector.py +0 -0
  122. {socket.d-2.4.10 → socket.d-2.4.10.2}/socketd_aio_tcp/TcpAioProvider.py +0 -0
  123. {socket.d-2.4.10 → socket.d-2.4.10.2}/socketd_aio_tcp/__init__.py +0 -0
  124. {socket.d-2.4.10 → socket.d-2.4.10.2}/socketd_websocket/WsAioChannelAssistant.py +0 -0
  125. {socket.d-2.4.10 → socket.d-2.4.10.2}/socketd_websocket/WsAioClient.py +0 -0
  126. {socket.d-2.4.10 → socket.d-2.4.10.2}/socketd_websocket/WsAioClientConnector.py +0 -0
  127. {socket.d-2.4.10 → socket.d-2.4.10.2}/socketd_websocket/WsAioProvider.py +0 -0
  128. {socket.d-2.4.10 → socket.d-2.4.10.2}/socketd_websocket/WsAioServer.py +0 -0
  129. {socket.d-2.4.10 → socket.d-2.4.10.2}/socketd_websocket/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: socket.d
3
- Version: 2.4.10
3
+ Version: 2.4.10.2
4
4
  Summary: @noear/socket.d python project
5
5
  Home-page: https://socketd.noear.org/
6
6
  Author: noear,bai
@@ -0,0 +1,42 @@
1
+
2
+
3
+ 基于事件和语义消息流的网络应用层协议。
4
+
5
+ 有用户说,“Socket.D 之于 Socket,尤如 Vue 之于 Js、Mvc 之于 Http”。支持 tcp, udp, ws, kcp 传输。
6
+
7
+ ```
8
+ [len:int][flag:int][sid:str(<64)][\n][event:str(<512)][\n][metaString:str(<4k)][\n][data:byte(<16m)]
9
+ ```
10
+
11
+ ### 主要特性
12
+
13
+ * 基于事件,每个消息都可事件路由
14
+ * 所谓语义,通过元信息进行语义描述
15
+ * 流关联性,来回相关的消息会串成一个流
16
+ * 语言无关,使用二进制输传数据(支持 tcp, ws, udp)。支持多语言、多平台
17
+ * 断线重连,自动连接恢复
18
+ * 多路复用,一个连接便可允许多个请求和响应消息同时运行
19
+ * 双向通讯,单链接双向互听互发
20
+ * 自动分片,数据超出 16Mb(大小可配置),会自动分片、自动重组(udp 除外)
21
+ * 接口简单,是响应式但用回调接口
22
+
23
+ ### 体验效果 (for python-client)
24
+
25
+ ```python
26
+ #发送
27
+ session.send("/demo/hello", StringEntity("hi"));
28
+ #发送,且获取发送进度(如果有大数据发送,又需要显示进度)
29
+ session.send("/demo/upload", FileEntity(file)).then_progress(lambda isSend, val, max: ...)
30
+
31
+ #发送并请求,且同步等待
32
+ reply = await session.send_and_request("/demo/hello", EntityDefault());
33
+ #发送并请求,且取接收进度(如果有大数据获取,又需要显示进度)
34
+ session.send_and_request("/demo/download", EntityDefault())
35
+ .then_progress(lambda isSend, val, max: ...)
36
+ .thenReply(lambda reply: ...)
37
+ .thenError(lambda err: ...)
38
+
39
+ #发送并订阅
40
+ entity = EntityDefault().range(5,5).meta_put("videoId","1");
41
+ session.send_and_subscribe("/demo/stream", entity).then_reply(lambda reply: ...)
42
+ ```
@@ -4,11 +4,11 @@ from setuptools import setup,find_packages
4
4
 
5
5
  setup(
6
6
  name='socket.d',
7
- version='2.4.10',
7
+ version='2.4.10.2',
8
8
  description='@noear/socket.d python project',
9
9
  author='noear,bai',
10
10
  url='https://socketd.noear.org/',
11
- packages=["socketd","socketd_aio_tcp","socketd_websocket"], # 包内不需要引用的文件夹
11
+ packages=find_packages(exclude=['*test*']), # 包内不需要引用的文件夹
12
12
  install_requires=[ # 依赖包
13
13
  'loguru',
14
14
  'websockets'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: socket.d
3
- Version: 2.4.10
3
+ Version: 2.4.10.2
4
4
  Summary: @noear/socket.d python project
5
5
  Home-page: https://socketd.noear.org/
6
6
  Author: noear,bai
@@ -0,0 +1,125 @@
1
+ README.md
2
+ setup.py
3
+ socket.d.egg-info/PKG-INFO
4
+ socket.d.egg-info/SOURCES.txt
5
+ socket.d.egg-info/dependency_links.txt
6
+ socket.d.egg-info/requires.txt
7
+ socket.d.egg-info/top_level.txt
8
+ socket.d.egg-info/zip-safe
9
+ socketd/SocketD.py
10
+ socketd/__init__.py
11
+ socketd/broker/BrokerFragmentHandler.py
12
+ socketd/broker/BrokerListener.py
13
+ socketd/broker/BrokerListenerBase.py
14
+ socketd/broker/__init__.py
15
+ socketd/cluster/ClusterClient.py
16
+ socketd/cluster/ClusterClientSession.py
17
+ socketd/cluster/LoadBalancer.py
18
+ socketd/cluster/__init__.py
19
+ socketd/exception/SocketDExecption.py
20
+ socketd/exception/__init__.py
21
+ socketd/transport/__init__.py
22
+ socketd/transport/client/Client.py
23
+ socketd/transport/client/ClientBase.py
24
+ socketd/transport/client/ClientChannel.py
25
+ socketd/transport/client/ClientConfig.py
26
+ socketd/transport/client/ClientConfigHandler.py
27
+ socketd/transport/client/ClientConnectHandler.py
28
+ socketd/transport/client/ClientConnector.py
29
+ socketd/transport/client/ClientConnectorBase.py
30
+ socketd/transport/client/ClientHandshakeResult.py
31
+ socketd/transport/client/ClientHeartbeatHandler.py
32
+ socketd/transport/client/ClientProvider.py
33
+ socketd/transport/client/ClientSession.py
34
+ socketd/transport/client/__init__.py
35
+ socketd/transport/core/Asserts.py
36
+ socketd/transport/core/Channel.py
37
+ socketd/transport/core/ChannelAssistant.py
38
+ socketd/transport/core/ChannelInternal.py
39
+ socketd/transport/core/ChannelSupporter.py
40
+ socketd/transport/core/Codec.py
41
+ socketd/transport/core/Config.py
42
+ socketd/transport/core/Costants.py
43
+ socketd/transport/core/Entity.py
44
+ socketd/transport/core/EntityMetas.py
45
+ socketd/transport/core/Flags.py
46
+ socketd/transport/core/FragmentAggregator.py
47
+ socketd/transport/core/FragmentHandler.py
48
+ socketd/transport/core/Frame.py
49
+ socketd/transport/core/Frames.py
50
+ socketd/transport/core/HandshakeDefault.py
51
+ socketd/transport/core/IdGenerator.py
52
+ socketd/transport/core/Listener.py
53
+ socketd/transport/core/Message.py
54
+ socketd/transport/core/Processor.py
55
+ socketd/transport/core/Session.py
56
+ socketd/transport/core/__init__.py
57
+ socketd/transport/core/codec/Buffer.py
58
+ socketd/transport/core/codec/ByteBufferCodecReader.py
59
+ socketd/transport/core/codec/ByteBufferCodecWriter.py
60
+ socketd/transport/core/codec/CodecDefault.py
61
+ socketd/transport/core/codec/__init__.py
62
+ socketd/transport/core/entity/EntityDefault.py
63
+ socketd/transport/core/entity/FileEntity.py
64
+ socketd/transport/core/entity/MessageBuilder.py
65
+ socketd/transport/core/entity/MessageDefault.py
66
+ socketd/transport/core/entity/StringEntity.py
67
+ socketd/transport/core/entity/__init__.py
68
+ socketd/transport/core/fragment/FragmentAggregatorDefault.py
69
+ socketd/transport/core/fragment/FragmentHandlerBase.py
70
+ socketd/transport/core/fragment/FragmentHandlerDefault.py
71
+ socketd/transport/core/fragment/FragmentHolder.py
72
+ socketd/transport/core/fragment/__init__.py
73
+ socketd/transport/core/impl/ChannelBase.py
74
+ socketd/transport/core/impl/ChannelDefault.py
75
+ socketd/transport/core/impl/ConfigBase.py
76
+ socketd/transport/core/impl/LogConfig.py
77
+ socketd/transport/core/impl/ProcessorDefault.py
78
+ socketd/transport/core/impl/SessionBase.py
79
+ socketd/transport/core/impl/SessionDefault.py
80
+ socketd/transport/core/impl/__init__.py
81
+ socketd/transport/core/listener/EventListener.py
82
+ socketd/transport/core/listener/PathListener.py
83
+ socketd/transport/core/listener/PathMapper.py
84
+ socketd/transport/core/listener/PipelineListener.py
85
+ socketd/transport/core/listener/SimpleListener.py
86
+ socketd/transport/core/listener/__init__.py
87
+ socketd/transport/server/Server.py
88
+ socketd/transport/server/ServerBase.py
89
+ socketd/transport/server/ServerConfig.py
90
+ socketd/transport/server/ServerProvider.py
91
+ socketd/transport/server/__init__.py
92
+ socketd/transport/stream/RequestStream.py
93
+ socketd/transport/stream/SendStream.py
94
+ socketd/transport/stream/Stream.py
95
+ socketd/transport/stream/StreamBase.py
96
+ socketd/transport/stream/StreamManger.py
97
+ socketd/transport/stream/StreamMangerDefault.py
98
+ socketd/transport/stream/SubscribeStream.py
99
+ socketd/transport/stream/__init__.py
100
+ socketd/transport/utils/AsyncUtil.py
101
+ socketd/transport/utils/CompletableFuture.py
102
+ socketd/transport/utils/StrUtil.py
103
+ socketd/transport/utils/__init__.py
104
+ socketd/transport/utils/async_api/AtomicRefer.py
105
+ socketd/transport/utils/async_api/__init__.py
106
+ socketd/transport/utils/sync_api/AtomicRefer.py
107
+ socketd/transport/utils/sync_api/__init__.py
108
+ socketd_aio_tcp/TCPAIOServer.py
109
+ socketd_aio_tcp/TCPStreamIO.py
110
+ socketd_aio_tcp/TcpAIOChannelAssistant.py
111
+ socketd_aio_tcp/TcpAioClient.py
112
+ socketd_aio_tcp/TcpAioClientConnector.py
113
+ socketd_aio_tcp/TcpAioProvider.py
114
+ socketd_aio_tcp/__init__.py
115
+ socketd_websocket/WsAioChannelAssistant.py
116
+ socketd_websocket/WsAioClient.py
117
+ socketd_websocket/WsAioClientConnector.py
118
+ socketd_websocket/WsAioProvider.py
119
+ socketd_websocket/WsAioServer.py
120
+ socketd_websocket/__init__.py
121
+ socketd_websocket/impl/AIOConnect.py
122
+ socketd_websocket/impl/AIOServe.py
123
+ socketd_websocket/impl/AIOWebSocketClientImpl.py
124
+ socketd_websocket/impl/AIOWebSocketServerImpl.py
125
+ socketd_websocket/impl/__init__.py
@@ -0,0 +1,7 @@
1
+ from socketd.transport.core.fragment.FragmentHandlerDefault import FragmentHandlerDefault
2
+
3
+
4
+ # 经纪人分片处理(关掉聚合)
5
+ class BrokerFragmentHandler(FragmentHandlerDefault):
6
+ def aggr_enable(self) -> bool:
7
+ return False
@@ -0,0 +1,93 @@
1
+ from socketd.broker.BrokerListenerBase import BrokerListenerBase
2
+ from socketd.transport.core import Entity
3
+ from socketd.transport.core.Message import Message
4
+ from socketd.transport.core.Session import Session
5
+
6
+
7
+ # 经纪人监听器(为不同的玩家转发消息)
8
+ class BrokerListener(BrokerListenerBase):
9
+ def __init__(self):
10
+ super().__init__()
11
+
12
+ async def on_open(self, session: Session):
13
+ name = session.name()
14
+ self.add_player(name, session)
15
+
16
+ def on_close(self, session: Session):
17
+ name = session.name()
18
+ self.remove_player(name, session)
19
+
20
+ async def on_message(self, requester: Session, message: Message):
21
+ atName = message.at_name()
22
+
23
+ if atName is None:
24
+ await requester.send_alarm(message, "Broker message require '@' meta")
25
+ return
26
+
27
+ if atName.__eq__("*"):
28
+ # 广播模式(给所有玩家)
29
+ nameAll = self.get_name_all()
30
+ if nameAll is not None and len(nameAll) > 0:
31
+ for name in nameAll:
32
+ self.forward_to_name(requester, message, name)
33
+ elif atName.endswith("*"):
34
+ # 群发模式(给同名的所有玩家)
35
+ atName = atName[:-1]
36
+ if not self.forward_to_name(requester, message, atName):
37
+ await requester.send_alarm(message, "Broker don't have '@" + atName + "' player")
38
+ else:
39
+ responder = self.get_player_any(atName, requester, message)
40
+ if responder is not None:
41
+ self.forward_to_session(requester, message, responder)
42
+ else:
43
+ await requester.send_alarm(message, "Broker don't have '@" + atName + "' session")
44
+
45
+ # 批量转发消息
46
+ def forward_to_name(self, requester: Session, message: Message, name: str) -> bool:
47
+ playerAll = self.get_player_all(name)
48
+
49
+ if playerAll is not None and len(playerAll) > 0:
50
+ for responder in playerAll:
51
+ if responder != requester:
52
+ if responder.is_valid():
53
+ self.forward_to_session(requester, message, responder)
54
+ else:
55
+ self.on_close(responder)
56
+ return True
57
+ else:
58
+ return False
59
+
60
+ # 转发消息
61
+ def forward_to_session(self, requester: Session, message: Message, responder: Session):
62
+ if message.is_request():
63
+ def then_reply(reply: Entity):
64
+ if requester.is_valid():
65
+ requester.reply(message, reply)
66
+
67
+ def then_error(err: Exception):
68
+ if requester.is_valid():
69
+ requester.send_alarm(message, err)
70
+
71
+ responder.send_and_request(message.event(), message, -1).then_reply(then_reply).then_error(then_error)
72
+ return
73
+
74
+ if message.is_subscribe():
75
+ def then_reply(reply: Entity):
76
+ if requester.is_valid():
77
+ if message.is_end():
78
+ requester.reply_end(message, reply)
79
+ else:
80
+ requester.reply(message, reply)
81
+
82
+ def then_error(err: Exception):
83
+ if requester.is_valid():
84
+ requester.send_alarm(message, err)
85
+
86
+ responder.send_and_subscribe(message.event(), message, -1).then_reply(then_reply).then_error(then_error)
87
+ return
88
+
89
+ responder.send(message.event(), message)
90
+
91
+ def on_error(self, session: Session, error):
92
+ ...
93
+ # log.warn("Broker error", error)
@@ -0,0 +1,82 @@
1
+ from abc import ABC
2
+ from typing import Dict, List
3
+ from socketd.cluster.LoadBalancer import LoadBalancer
4
+ from socketd.transport.client.ClientSession import ClientSession
5
+ from socketd.transport.core.EntityMetas import EntityMetas
6
+ from socketd.transport.core.Listener import Listener
7
+ from socketd.transport.core.Message import Message
8
+ from socketd.transport.core.Session import Session
9
+ from socketd.transport.utils.StrUtil import StrUtil
10
+
11
+
12
+ # 经纪人监听器基类(实现玩家封闭管理)
13
+ class BrokerListenerBase(Listener, ABC):
14
+ def __init__(self):
15
+ self.__sessionAll: Dict[str, Session] = {}
16
+ self.__playerSessions: Dict[str, List[Session]] = {}
17
+
18
+ # 获取所有会话(包括没有名字的)
19
+ def get_session_all(self) -> List[Session]:
20
+ return list(self.__sessionAll.values())
21
+
22
+ # 获取任意会话(包括没有名字的)
23
+ def get_session_any(self) -> ClientSession:
24
+ return LoadBalancer.get_any(self.get_session_all(), LoadBalancer.round_counter_get())
25
+
26
+ # 获取会话数量
27
+ def get_session_count(self) -> int:
28
+ return len(self.__sessionAll)
29
+
30
+ # 获取所有玩家的名字
31
+ def get_name_all(self) -> List[str]:
32
+ return list(self.__sessionAll.keys())
33
+
34
+ # 获取所有玩家数量
35
+ def get_player_count(self, name: str) -> int:
36
+ return len(self.get_player_all(name))
37
+
38
+ # 获取所有玩家会话
39
+ def get_player_all(self, name: str) -> List[Session]:
40
+ return self.__playerSessions[name]
41
+
42
+ # 获取任意一个玩家会话
43
+ def get_player_any(self, atName: str, requester: Session | None, message: Message | None) -> ClientSession | None:
44
+ if StrUtil.is_empty(atName):
45
+ return None
46
+
47
+ if atName.endswith("!"):
48
+ atName = atName[:-1]
49
+ x_hash = None
50
+
51
+ if message is not None:
52
+ x_hash = message.meta(EntityMetas.META_X_Hash)
53
+
54
+ if StrUtil.is_empty(x_hash):
55
+ if requester is None:
56
+ return LoadBalancer.get_any_by_poll(self.get_player_all(atName))
57
+ else: # 使用请求者 ip 分流
58
+ return LoadBalancer.get_any_by_hash(self.get_player_all(atName), requester.remote_address())
59
+ else:
60
+ return LoadBalancer.get_any_by_hash(self.get_player_all(atName), x_hash)
61
+ else:
62
+ return LoadBalancer.get_any_by_poll(self.get_player_all(atName))
63
+
64
+ # 添加玩家会话
65
+ def add_player(self, name: str, session: Session):
66
+ if StrUtil.is_not_empty(name):
67
+ tmp: List[Session] = self.__playerSessions.get(name)
68
+ if tmp is None:
69
+ tmp = [session]
70
+ self.__playerSessions[name] = tmp
71
+ tmp.append(session)
72
+
73
+ self.__sessionAll[session.session_id()] = session
74
+
75
+ # 移除玩家会话
76
+ def remove_player(self, name: str, session: Session):
77
+ if StrUtil.is_not_empty(name):
78
+ tmp: list[Session] = self.get_player_all(name)
79
+ if tmp is not None:
80
+ tmp.remove(session)
81
+
82
+ self.__sessionAll.pop(session.session_id())
File without changes
@@ -0,0 +1,75 @@
1
+ import asyncio
2
+ from typing import Optional, List, Awaitable, Any
3
+
4
+ from socketd import SocketD
5
+ from socketd.cluster.ClusterClientSession import ClusterClientSession
6
+ from socketd.transport.client.Client import Client, ClientInternal
7
+ from socketd.transport.client.ClientConfigHandler import ClientConfigHandler
8
+ from socketd.transport.client.ClientConnectHandler import ClientConnectHandler
9
+ from socketd.transport.client.ClientSession import ClientSession
10
+ from socketd.transport.core import Listener
11
+ from socketd.transport.core.Session import Session
12
+ from socketd.transport.client.ClientHeartbeatHandler import ClientHeartbeatHandler
13
+
14
+
15
+ class ClusterClient(Client):
16
+
17
+ def __init__(self, *serverUrls):
18
+ self.__serverUrls: Optional[tuple[Any, ...]] = serverUrls
19
+
20
+ self.__connectHandler: ClientConnectHandler = None
21
+ self.__heartbeatHandler: ClientHeartbeatHandler = None
22
+ self.__configHandler: ClientConfigHandler = None
23
+
24
+ self.__listener = None
25
+
26
+ def connect_handler(self, connectHandler: ClientConnectHandler) -> Client:
27
+ self.__connectHandler = connectHandler
28
+ return self
29
+
30
+ def heartbeat_handler(self, heartbeatHandler: ClientHeartbeatHandler) -> Client:
31
+ self.__heartbeatHandler = heartbeatHandler
32
+ return self
33
+
34
+ def config(self, configHandler: ClientConfigHandler) -> Client:
35
+ self.__configHandler = configHandler
36
+ return self
37
+
38
+ def listen(self, listener: Listener) -> Client:
39
+ self.__listener = listener
40
+ return self
41
+
42
+ def open(self) -> Awaitable[ClientSession]:
43
+ return self._open_do(False)
44
+
45
+ def open_or_throw(self) -> Awaitable[ClientSession]:
46
+ return self._open_do(True)
47
+
48
+ async def _open_do(self, is_throw):
49
+ sessions: List[Session] = []
50
+ exchangeExecutor = None
51
+ for urls in self.__serverUrls:
52
+ for url in urls.split(","):
53
+ client: ClientInternal = SocketD.create_client(url)
54
+
55
+ if self.__listener:
56
+ client.listen(self.__listener)
57
+
58
+ if self.__configHandler:
59
+ client.config(self.__configHandler)
60
+
61
+ if self.__connectHandler:
62
+ client.connect_handler(self.__connectHandler)
63
+
64
+ if self.__heartbeatHandler:
65
+ client.heartbeat_handler(self.__heartbeatHandler)
66
+
67
+ if exchangeExecutor is None:
68
+ exchangeExecutor = client.get_config().get_exchange_executor()
69
+ else:
70
+ client.get_config().exchange_executor(exchangeExecutor)
71
+
72
+ sessions.extend(await asyncio.gather(*[client.open_or_throw() if is_throw else client.open()]))
73
+ return ClusterClientSession(sessions)
74
+
75
+
@@ -0,0 +1,80 @@
1
+ from socketd.cluster.LoadBalancer import LoadBalancer
2
+ from socketd.exception.SocketDExecption import SocketDException
3
+ from socketd.transport.client.ClientSession import ClientSession
4
+ from socketd.transport.core import Entity
5
+ from socketd.transport.stream.RequestStream import RequestStream
6
+ from socketd.transport.stream.SendStream import SendStream
7
+ from socketd.transport.stream.SubscribeStream import SubscribeStream
8
+ from socketd.transport.utils.StrUtil import StrUtil
9
+
10
+
11
+ class ClusterClientSession(ClientSession):
12
+
13
+ def __init__(self, _sessionSet):
14
+ self.__sessionSet: list[ClientSession] = _sessionSet
15
+ self.__sessionId = StrUtil.guid()
16
+
17
+ def get_session_all(self) -> list[ClientSession]:
18
+ return self.__sessionSet
19
+
20
+ def get_session_any(self, diversionOrNull: str | None) -> ClientSession:
21
+ session: ClientSession
22
+
23
+ if diversionOrNull:
24
+ session = LoadBalancer.get_any_by_poll(self.__sessionSet)
25
+ else:
26
+ session = LoadBalancer.get_any_by_hash(self.__sessionSet, diversionOrNull)
27
+
28
+ if session:
29
+ return session
30
+ else:
31
+ raise SocketDException("No session is available!")
32
+
33
+ def is_valid(self) -> bool:
34
+ for session in self.__sessionSet:
35
+ if session.is_valid():
36
+ return True
37
+ return False
38
+
39
+ def is_closing(self) -> bool:
40
+ for session in self.__sessionSet:
41
+ if session.is_closing():
42
+ return True
43
+ return False
44
+
45
+ def session_id(self) -> str:
46
+ return self.__sessionId
47
+
48
+ async def send(self, event: str, content: Entity) -> SendStream:
49
+ sender = self.get_session_any(None)
50
+
51
+ return await sender.send(event, content)
52
+
53
+ async def send_and_request(self, event: str, content: Entity, timeout: int) -> RequestStream:
54
+ sender = self.get_session_any(None)
55
+
56
+ return await sender.send_and_request(event, content, timeout)
57
+
58
+ async def send_and_subscribe(self, event: str, content: Entity, timeout: int = 0) -> SubscribeStream:
59
+ sender = self.get_session_any(None)
60
+
61
+ return await sender.send_and_subscribe(event, content, timeout)
62
+
63
+ async def preclose(self):
64
+ for session in self.__sessionSet:
65
+ try:
66
+ await session.preclose()
67
+ except RuntimeError as e:
68
+ pass
69
+
70
+ async def close(self):
71
+ for session in self.__sessionSet:
72
+ try:
73
+ await session.close()
74
+ except RuntimeError as e:
75
+ pass
76
+
77
+ async def reconnect(self):
78
+ for session in self.__sessionSet:
79
+ if not session.is_valid():
80
+ await session.reconnect()
@@ -0,0 +1,65 @@
1
+ from threading import RLock
2
+ from typing import List
3
+
4
+ from socketd.transport.client.ClientSession import ClientSession
5
+ from socketd.transport.utils.StrUtil import StrUtil
6
+
7
+
8
+ class LoadBalancer:
9
+ __roundCounter: int = 0 # 轮环计数器
10
+ __lock: RLock = RLock() # 计数锁
11
+
12
+ @staticmethod
13
+ def round_counter_get() -> int:
14
+ LoadBalancer.__lock.acquire()
15
+
16
+ try:
17
+ LoadBalancer.__roundCounter += 1
18
+ if LoadBalancer.__roundCounter > 999_999:
19
+ LoadBalancer.__roundCounter = 0
20
+ return LoadBalancer.__roundCounter
21
+ finally:
22
+ LoadBalancer.__lock.release()
23
+
24
+ # 根据 poll 获取任意一个
25
+ @staticmethod
26
+ def get_any_by_poll(coll: List[ClientSession]) -> ClientSession:
27
+ return LoadBalancer.get_any(coll, LoadBalancer.round_counter_get())
28
+
29
+ # 根据 hash 获取任意一个
30
+ @staticmethod
31
+ def get_any_by_hash(coll: List[ClientSession], diversion: str) -> ClientSession:
32
+ return LoadBalancer.get_any(coll, StrUtil.hash_code(diversion))
33
+
34
+ # 获取任意一个
35
+ @staticmethod
36
+ def get_any(coll: list[ClientSession], random: int) -> ClientSession | None:
37
+ if coll is None or coll.__len__() == 0:
38
+ return None
39
+ else:
40
+ sessions: List[ClientSession] = []
41
+ for s in coll:
42
+ if s.is_valid() and not s.is_closing():
43
+ sessions.append(s)
44
+
45
+ if sessions.__len__() == 0:
46
+ return None
47
+
48
+ if sessions.__len__() == 1:
49
+ return sessions[0]
50
+
51
+ random = abs(random)
52
+ idx = random % sessions.__len__()
53
+ return sessions[idx]
54
+
55
+ # 获取第一个
56
+ @staticmethod
57
+ def get_first(coll: List[ClientSession]):
58
+ if coll is None or coll.__len__() == 0:
59
+ return None
60
+ else:
61
+ for s in coll:
62
+ if s.is_valid() and not s.is_closing():
63
+ return s
64
+
65
+ return None
File without changes
@@ -0,0 +1,38 @@
1
+ class SocketDException(RuntimeError):
2
+
3
+ def __init__(self, message):
4
+ super().__init__(self)
5
+ self.message = message
6
+
7
+ def __str__(self):
8
+ return self.message
9
+
10
+
11
+ class SocketDAlarmException(SocketDException):
12
+ """ 告警"""
13
+ pass
14
+
15
+
16
+ class SocketDChannelException(SocketDException):
17
+ """ 通道"""
18
+ pass
19
+
20
+
21
+ class SocketDCodecException(SocketDException):
22
+ """ 编码"""
23
+ pass
24
+
25
+
26
+ class SocketDConnectionException(SocketDException):
27
+ """连接"""
28
+ pass
29
+
30
+
31
+ class SocketDSizeLimitException(SocketDException):
32
+ """ 超长"""
33
+ pass
34
+
35
+
36
+ class SocketDTimeoutException(SocketDException):
37
+ """ 超时"""
38
+ pass
File without changes
File without changes