litenetlib-0952 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,355 @@
1
+ """
2
+ Network manager for LiteNetLib v0.9.5.2 / LiteNetLib v0.9.5.2 网络管理器
3
+
4
+ Main class for all network operations. Can be used as client and/or server.
5
+ 所有网络操作的主类。可以用作客户端和/或服务器。
6
+
7
+ Ported from: LiteNetLib/NetManager.cs (v0.9.5.2)
8
+ """
9
+
10
+ import asyncio
11
+ import socket
12
+ import time
13
+ from typing import Dict, Optional, Set, Callable, Any
14
+ from litenetlib.core.constants import NetConstants, PacketProperty, DisconnectReason
15
+ from litenetlib.core.packet import NetPacket, NetPacketPool
16
+ from litenetlib.core.peer import NetPeer
17
+ from litenetlib.core.events import EventBasedNetListener, INetEventListener
18
+ from litenetlib.core.connection_request import ConnectionRequest
19
+ from litenetlib.utils.net_utils import NetUtils
20
+
21
+
22
+ class LiteNetManager:
23
+ """
24
+ Main network manager class / 主网络管理器类
25
+
26
+ Manages socket, peers, and network events.
27
+ 管理 socket、对等端和网络事件。
28
+
29
+ C# Reference: NetManager
30
+ """
31
+
32
+ def __init__(self, listener: Optional[INetEventListener] = None):
33
+ """
34
+ Create network manager / 创建网络管理器。
35
+
36
+ Args:
37
+ listener: Event listener for network events / 网络事件监听器
38
+ """
39
+ self._listener = listener
40
+ self._peers: Dict[tuple, NetPeer] = {}
41
+ self._socket: Optional[socket.socket] = None
42
+ self._running = False
43
+ self._packet_pool = NetPacketPool()
44
+ self._host: str = "0.0.0.0"
45
+ self._port: int = 0
46
+ self._max_peers: int = 10
47
+ self._auto_recycle = True
48
+
49
+ # Connection management / 连接管理
50
+ self._connect_time: int = 0
51
+ self._local_id: int = 0
52
+
53
+ @property
54
+ def peers_count(self) -> int:
55
+ """Get number of connected peers / 获取已连接对等端数量"""
56
+ return len(self._peers)
57
+
58
+ @property
59
+ def is_running(self) -> bool:
60
+ """Check if manager is running / 检查管理器是否正在运行"""
61
+ return self._running
62
+
63
+ @property
64
+ def local_port(self) -> int:
65
+ """Get local port / 获取本地端口"""
66
+ return self._port
67
+
68
+ @property
69
+ def listener(self) -> Optional[INetEventListener]:
70
+ """Get event listener / 获取事件监听器"""
71
+ return self._listener
72
+
73
+ @listener.setter
74
+ def listener(self, value: Optional[INetEventListener]) -> None:
75
+ """Set event listener / 设置事件监听器"""
76
+ self._listener = value
77
+
78
+ def start(self, port: int = 0, host: str = "0.0.0.0", max_peers: int = 10) -> bool:
79
+ """
80
+ Start network manager / 启动网络管理器。
81
+
82
+ Args:
83
+ port: Local port to bind to (0 for any available port) / 要绑定的本地端口
84
+ host: Local address to bind to / 要绑定的本地地址
85
+ max_peers: Maximum number of peers / 最大对等端数量
86
+
87
+ Returns:
88
+ True if started successfully / 如果成功启动则返回 True
89
+ """
90
+ if self._running:
91
+ return False
92
+
93
+ self._host = host
94
+ self._port = port
95
+ self._max_peers = max_peers
96
+
97
+ try:
98
+ # Create UDP socket / 创建 UDP socket
99
+ self._socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
100
+ self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
101
+ self._socket.bind((host, port))
102
+
103
+ # Get actual port if 0 was specified / 如果指定了 0,获取实际端口
104
+ if port == 0:
105
+ self._port = self._socket.getsockname()[1]
106
+
107
+ self._running = True
108
+ self._connect_time = NetUtils.get_time_ticks()
109
+ self._local_id = NetUtils.generate_connect_id()
110
+
111
+ return True
112
+ except Exception as e:
113
+ if self._socket:
114
+ self._socket.close()
115
+ self._socket = None
116
+ print(f"Failed to start manager: {e}")
117
+ return False
118
+
119
+ def stop(self) -> None:
120
+ """Stop network manager and disconnect all peers / 停止网络管理器并断开所有对等端"""
121
+ if not self._running:
122
+ return
123
+
124
+ # Disconnect all peers / 断开所有对等端
125
+ for peer in list(self._peers.values()):
126
+ peer.disconnect()
127
+
128
+ self._running = False
129
+
130
+ if self._socket:
131
+ self._socket.close()
132
+ self._socket = None
133
+
134
+ self._peers.clear()
135
+
136
+ def connect(self, host: str, port: int, connection_data: Optional[bytes] = None) -> bool:
137
+ """
138
+ Connect to remote host / 连接到远程主机。
139
+
140
+ Args:
141
+ host: Remote host address / 远程主机地址
142
+ port: Remote port / 远程端口
143
+ connection_data: Optional connection data / 可选的连接数据
144
+
145
+ Returns:
146
+ True if connection initiated successfully / 如果成功发起连接则返回 True
147
+ """
148
+ if not self._running:
149
+ return False
150
+
151
+ address = (host, port)
152
+ if address in self._peers:
153
+ return False
154
+
155
+ # Create peer / 创建对等端
156
+ peer = NetPeer(self, address, 0)
157
+ self._peers[address] = peer
158
+
159
+ # Send connect request / 发送连接请求
160
+ peer.send_connect_request(connection_data or b'')
161
+
162
+ return True
163
+
164
+ def get_peer_by_address(self, host: str, port: int) -> Optional[NetPeer]:
165
+ """
166
+ Get peer by address / 通过地址获取对等端。
167
+
168
+ Args:
169
+ host: Peer host address / 对等端主机地址
170
+ port: Peer port / 对等端端口
171
+
172
+ Returns:
173
+ NetPeer if found, None otherwise / 找到则返回 NetPeer,否则返回 None
174
+ """
175
+ return self._peers.get((host, port))
176
+
177
+ def send_to_all(
178
+ self,
179
+ data: bytes,
180
+ delivery_method: Any = None,
181
+ exclude_peer: Optional[NetPeer] = None
182
+ ) -> None:
183
+ """
184
+ Send data to all connected peers / 向所有已连接的对等端发送数据。
185
+
186
+ Args:
187
+ data: Data to send / 要发送的数据
188
+ delivery_method: Delivery method / 传输方法
189
+ exclude_peer: Peer to exclude from sending / 要排除的对等端
190
+ """
191
+ for peer in self._peers.values():
192
+ if peer != exclude_peer and peer.is_connected:
193
+ peer.send(data, delivery_method)
194
+
195
+ async def poll_async(self) -> None:
196
+ """
197
+ Async poll for network events / 异步轮询网络事件。
198
+
199
+ This method should be called in an async context to process network events.
200
+ 此方法应在异步上下文中调用以处理网络事件。
201
+ """
202
+ if not self._running or not self._socket:
203
+ return
204
+
205
+ try:
206
+ # Set socket to non-blocking / 设置 socket 为非阻塞
207
+ self._socket.setblocking(False)
208
+
209
+ while self._running:
210
+ try:
211
+ # Receive data / 接收数据
212
+ data, addr = self._socket.recvfrom(NetConstants.MAX_PACKET_SIZE)
213
+ await self._handle_packet(data, addr)
214
+ except BlockingIOError:
215
+ # No data available, wait a bit / 无可用数据,等待一下
216
+ await asyncio.sleep(0.001)
217
+ except Exception as e:
218
+ print(f"Error receiving data: {e}")
219
+
220
+ # Update peers / 更新对等端
221
+ current_time = NetUtils.get_time_millis()
222
+ for peer in list(self._peers.values()):
223
+ await peer.update_async(current_time)
224
+
225
+ except Exception as e:
226
+ print(f"Error in poll_async: {e}")
227
+
228
+ async def _handle_packet(self, data: bytes, addr: tuple) -> None:
229
+ """
230
+ Handle received packet / 处理接收到的数据包。
231
+
232
+ Args:
233
+ data: Packet data / 数据包数据
234
+ addr: Sender address / 发送者地址
235
+ """
236
+ try:
237
+ packet = NetPacket.from_bytes(data)
238
+
239
+ if not packet.verify():
240
+ return
241
+
242
+ peer = self._peers.get(addr)
243
+
244
+ # Handle packet based on property / 根据属性处理数据包
245
+ prop = packet.packet_property
246
+
247
+ if prop == PacketProperty.CONNECT_REQUEST:
248
+ await self._handle_connect_request(packet, addr)
249
+ elif prop == PacketProperty.CONNECT_ACCEPT:
250
+ if peer:
251
+ await peer.handle_connect_accept(packet)
252
+ elif prop == PacketProperty.DISCONNECT:
253
+ if peer:
254
+ await self._handle_disconnect(peer, packet)
255
+ elif prop == PacketProperty.ACK:
256
+ if peer:
257
+ await peer.handle_ack(packet)
258
+ elif prop in [PacketProperty.CHANNELED, PacketProperty.UNRELIABLE]:
259
+ if peer:
260
+ await peer.handle_data_packet(packet)
261
+ else:
262
+ # Other packet types / 其他数据包类型
263
+ if peer:
264
+ await peer.process_packet(packet)
265
+
266
+ except Exception as e:
267
+ print(f"Error handling packet from {addr}: {e}")
268
+
269
+ async def _handle_connect_request(self, packet: NetPacket, addr: tuple) -> None:
270
+ """
271
+ Handle connection request / 处理连接请求。
272
+
273
+ Args:
274
+ packet: Connection request packet / 连接请求数据包
275
+ addr: Sender address / 发送者地址
276
+ """
277
+ from litenetlib.core.internal_packets import NetConnectRequestPacket
278
+
279
+ request = NetConnectRequestPacket.from_data(packet)
280
+ if not request:
281
+ return
282
+
283
+ # Check if we can accept more peers / 检查是否可以接受更多对等端
284
+ if len(self._peers) >= self._max_peers:
285
+ # Send reject / 发送拒绝
286
+ self._send_reject(addr)
287
+ return
288
+
289
+ # Check protocol ID / 检查协议 ID
290
+ protocol_id = NetConnectRequestPacket.get_protocol_id(packet)
291
+ if protocol_id != NetConstants.PROTOCOL_ID:
292
+ # Send invalid protocol / 发送无效协议
293
+ self._send_invalid_protocol(addr)
294
+ return
295
+
296
+ # Create connection request event / 创建连接请求事件
297
+ conn_request = ConnectionRequest(self, addr, request)
298
+
299
+ if self._listener:
300
+ # Let listener decide / 让监听器决定
301
+ if self._listener.on_connection_request(conn_request):
302
+ # Accepted / 已接受
303
+ peer = NetPeer(self, addr, request.connection_number)
304
+ self._peers[addr] = peer
305
+ await peer.accept_connection(request)
306
+ else:
307
+ # Rejected / 已拒绝
308
+ conn_request.reject()
309
+ else:
310
+ # Auto-accept / 自动接受
311
+ peer = NetPeer(self, addr, request.connection_number)
312
+ self._peers[addr] = peer
313
+ await peer.accept_connection(request)
314
+
315
+ async def _handle_disconnect(self, peer: NetPeer, packet: NetPacket) -> None:
316
+ """
317
+ Handle disconnect packet / 处理断开连接数据包。
318
+
319
+ Args:
320
+ peer: Peer that disconnected / 断开连接的对等端
321
+ packet: Disconnect packet / 断开连接数据包
322
+ """
323
+ addr = peer.address
324
+ peer.shutdown()
325
+
326
+ if addr in self._peers:
327
+ del self._peers[addr]
328
+
329
+ if self._listener:
330
+ self._listener.on_peer_disconnect(peer, DisconnectReason.REMOTE_CONNECTION_CLOSE)
331
+
332
+ def _send_reject(self, addr: tuple) -> None:
333
+ """Send connection reject / 发送连接拒绝"""
334
+ packet = NetPacket(PacketProperty.DISCONNECT, 8)
335
+ # Write reject reason / 写入拒绝原因
336
+ if self._socket:
337
+ self._socket.sendto(packet.get_bytes(), addr)
338
+
339
+ def _send_invalid_protocol(self, addr: tuple) -> None:
340
+ """Send invalid protocol response / 发送无效协议响应"""
341
+ packet = NetPacket(PacketProperty.INVALID_PROTOCOL)
342
+ if self._socket:
343
+ self._socket.sendto(packet.get_bytes(), addr)
344
+
345
+ def get_packet_from_pool(self, size: int) -> NetPacket:
346
+ """Get packet from pool / 从池中获取数据包"""
347
+ return self._packet_pool.get(size)
348
+
349
+ def recycle_packet(self, packet: NetPacket) -> None:
350
+ """Recycle packet to pool / 将数据包回收至池中"""
351
+ self._packet_pool.recycle(packet)
352
+
353
+ def __del__(self):
354
+ """Cleanup on destruction / 销毁时清理"""
355
+ self.stop()