socket_pro 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.
socket_pro/__init__.py ADDED
File without changes
File without changes
@@ -0,0 +1,11 @@
1
+ from socket_pro.socket_client import SocketClient
2
+
3
+ if __name__ == "__main__":
4
+
5
+ client = SocketClient("192.168.6.6", 9102)
6
+ if client.connect():
7
+ try:
8
+ result = client.send_data(b"TRIGGER")
9
+ print(result)
10
+ finally:
11
+ client.disconnect()
@@ -0,0 +1,95 @@
1
+ # pylint: skip-file
2
+ import socket
3
+ import logging
4
+
5
+
6
+ class SocketClient:
7
+ """用于持续与服务器通信的 TCP Socket 客户端."""
8
+
9
+ def __init__(self, host: str, port: int, buffer_size: int = 1024, time_out: int = 3):
10
+ """初始化 Socket 客户端.
11
+
12
+ Args:
13
+ host: 要连接的服务器主机名或 IP 地址.
14
+ port: 服务器端口号.
15
+ buffer_size: 接收缓冲区大小(字节),默认为 1024.
16
+ time_out: 等待回复超时时间, 默认 3 秒.
17
+ """
18
+ self.host = host
19
+ self.port = port
20
+ self.buffer_size = buffer_size
21
+ self.time_out = time_out
22
+ self.socket = None
23
+ self.is_connected = False
24
+ self.receive_thread = None
25
+ self.logger = logging.getLogger(self.__class__.__name__)
26
+
27
+ def connect(self) -> tuple[bool, str]:
28
+ """建立与服务器的连接, 连接成功后会自动启动后台线程持续接收数据.
29
+
30
+ Args:
31
+
32
+ Returns:
33
+ tuple[bool, str]: 连接成功返回 (True, 描述信息), 否则返回 (False, 错误信息).
34
+ """
35
+ try:
36
+ if self.is_connected:
37
+ return True, "连接成功"
38
+ self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
39
+ self.socket.connect((self.host, self.port))
40
+ self.socket.settimeout(self.time_out)
41
+ self.is_connected = True
42
+ self.logger.info("已连接到服务器 %s: %s", self.host, self.port)
43
+ return True, "连接成功"
44
+ except Exception as e:
45
+ self.logger.warning("连接失败, %s", str(e))
46
+ self.is_connected = False
47
+ return False, str(e)
48
+
49
+ def disconnect(self):
50
+ """断开与服务器的连接并释放资源."""
51
+ if self.is_connected:
52
+ self.is_connected = False
53
+ try:
54
+ if self.socket:
55
+ self.socket.close()
56
+ if self.receive_thread and self.receive_thread.is_alive():
57
+ self.receive_thread.join(timeout=1)
58
+ except Exception as e:
59
+ self.logger.warning("断开连接时出错: %s", str(e))
60
+ finally:
61
+ self.logger.info("已断开与服务器的连接")
62
+
63
+ def send_data(self, data: bytes, wait_response: bool = True) -> tuple[bool, str]:
64
+ """向服务器发送数据.
65
+
66
+ Args:
67
+ data: 要发送的字节数据.
68
+ wait_response: 是否需要回复, 默认需要回复.
69
+
70
+ Returns:
71
+ tuple[bool, str]: 发送成功返回 (True, 成功信息), 失败返回 (False, 失败信息).
72
+ """
73
+ if not self.is_connected:
74
+ self.logger.warning("未连接到服务器")
75
+ return False, "未连接服务端"
76
+
77
+ try:
78
+ self.socket.sendall(data)
79
+ if wait_response:
80
+ response = self.socket.recv(self.buffer_size)
81
+ return True, response.decode("UTF-8")
82
+ return True, "发送成功, 不需要等待回复"
83
+ except Exception as e:
84
+ self.logger.warning("发送数据出错: %s", str(e))
85
+ self.disconnect()
86
+ return False, str(e)
87
+
88
+ def __enter__(self):
89
+ """实现上下文管理协议,进入时自动连接."""
90
+ self.connect()
91
+ return self
92
+
93
+ def __exit__(self, exc_type, exc_val, exc_tb):
94
+ """实现上下文管理协议,退出时自动断开连接."""
95
+ self.disconnect()
@@ -0,0 +1,88 @@
1
+ # pylint: skip-file
2
+ """异步socket."""
3
+ import asyncio
4
+ import logging
5
+ import socket
6
+ from asyncio import AbstractEventLoop
7
+
8
+
9
+ class SocketServerAsyncio:
10
+ """异步 socket class."""
11
+ loop: AbstractEventLoop = None
12
+
13
+ def __init__(self, address: str = "127.0.0.1", port: int = 1830, save_log: bool = False):
14
+ """SocketServerAsyncio 构造方法.
15
+
16
+ Args:
17
+ address: 服务端 ip address.
18
+ port: 服务端端口.
19
+ save_log: 是否保存日志, 默认不保存.
20
+ """
21
+ self.clients = {} # 保存已连接的client
22
+ self.tasks = {}
23
+ self.save_log = save_log
24
+ self._address = address
25
+ self._port = port
26
+ self.logger = logging.getLogger(__name__)
27
+
28
+ async def operations_return_data(self, data: bytes):
29
+ """操作返回数据."""
30
+ data = data.decode("UTF-8")
31
+ self.logger.warning("没有重写 operations_return_data 函数, 默认是回显.")
32
+ return data
33
+
34
+ async def socket_send(self, client_connection, data: bytes):
35
+ """发送数据给客户端."""
36
+ if client_connection:
37
+ client_ip = client_connection.getpeername()
38
+ await self.loop.sock_sendall(client_connection, data)
39
+ self.logger.info("%s 发送成功, %s", client_ip, data)
40
+ else:
41
+ self.logger.info("发送数据 % 失败", data)
42
+
43
+ async def receive_send(self, client_connection: socket.socket):
44
+ """接收后发送数据."""
45
+ client_ip = client_connection.getpeername()[0] # 获取连接客户端的ip
46
+ try:
47
+ while data := await self.loop.sock_recv(client_connection, 1024 * 1024):
48
+ self.logger.info("%s", "-" * 60)
49
+ self.logger.info("接收到客户端 %s 的数据: %s", client_ip, data.decode("UTF-8"))
50
+ send_data = await self.operations_return_data(data) # 这个方法实现具体业务, 需要重写, 不重写回显
51
+ send_data_byte = send_data.encode("UTF-8")
52
+ await self.loop.sock_sendall(client_connection, send_data_byte)
53
+ self.logger.info("回复客户端 %s 的数据是: %s", client_ip, send_data)
54
+ self.logger.info("%s", "-" * 60)
55
+ except Exception as e: # pylint: disable=W0718
56
+ self.logger.warning("通讯出现异常, 异常信息是: %s", str(e))
57
+ finally:
58
+ self.clients.pop(client_ip)
59
+ self.tasks.get(client_ip).cancel()
60
+ self.logger.warning("客户端 %s 断开了", client_ip)
61
+ client_connection.close()
62
+
63
+ async def listen_for_connection(self, socket_server: socket.socket):
64
+ """异步监听连接.
65
+
66
+ Args:
67
+ socket_server: socket.socket 实例.
68
+ """
69
+ self.logger.info("服务端 %s 已启动,等待客户端连接", socket_server.getsockname())
70
+
71
+ while True:
72
+ self.loop = asyncio.get_running_loop()
73
+ client_connection, address = await self.loop.sock_accept(socket_server)
74
+ client_connection.setblocking(False)
75
+ self.clients.update({address[0]: client_connection})
76
+ self.tasks.update({
77
+ address[0]: self.loop.create_task(self.receive_send(client_connection))
78
+ })
79
+ self.logger.warning("客户端 %s 连接了", address)
80
+
81
+ async def run_socket_server(self):
82
+ """运行socket服务, 并监听客户端连接."""
83
+ socket_server = socket.socket()
84
+ socket_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
85
+ socket_server.setblocking(False)
86
+ socket_server.bind((self._address, self._port))
87
+ socket_server.listen()
88
+ await self.listen_for_connection(socket_server)
@@ -0,0 +1,19 @@
1
+ Metadata-Version: 2.4
2
+ Name: socket_pro
3
+ Version: 1.0.0
4
+ Summary: socket 封装
5
+ Author: LiuWei
6
+ Author-email: 183074632@qq.com
7
+ Requires-Python: >=3.8,<=3.13
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.8
10
+ Classifier: Programming Language :: Python :: 3.9
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Description-Content-Type: text/markdown
16
+
17
+ # socket_pro
18
+ 异步socket
19
+
@@ -0,0 +1,8 @@
1
+ socket_pro/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ socket_pro/example/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ socket_pro/example/client_example.py,sha256=Lb6_y39TbWjkH3ZPoCRqHIFMN24knZWT72gQkOk4y_w,298
4
+ socket_pro/socket_client.py,sha256=Cx6gJfiJrFbFIoh8haXxxxeI6oaBviGjOvKp2HRuC18,3601
5
+ socket_pro/socket_server_asyncio.py,sha256=vRWQzMBqlVIS3VofFWWq1hN7REjP8pQmRjYveFNHhXU,3832
6
+ socket_pro-1.0.0.dist-info/METADATA,sha256=joKNbeNNsPP8elQoXmdGwvhyQBDQw8OrRMeDbvnEni0,573
7
+ socket_pro-1.0.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
8
+ socket_pro-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 2.2.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any