knotlink 0.0.0__tar.gz
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.
- knotlink-0.0.0/PKG-INFO +13 -0
- knotlink-0.0.0/README.md +1 -0
- knotlink-0.0.0/knotlink/OpenSocketQuerier.py +92 -0
- knotlink-0.0.0/knotlink/OpenSocketResponser.py +96 -0
- knotlink-0.0.0/knotlink/SignalSender.py +51 -0
- knotlink-0.0.0/knotlink/SignalSubscriber.py +71 -0
- knotlink-0.0.0/knotlink/__init__.py +22 -0
- knotlink-0.0.0/knotlink/kludf.py +66 -0
- knotlink-0.0.0/knotlink/tcpclient.py +100 -0
- knotlink-0.0.0/knotlink.egg-info/PKG-INFO +13 -0
- knotlink-0.0.0/knotlink.egg-info/SOURCES.txt +13 -0
- knotlink-0.0.0/knotlink.egg-info/dependency_links.txt +1 -0
- knotlink-0.0.0/knotlink.egg-info/top_level.txt +1 -0
- knotlink-0.0.0/setup.cfg +4 -0
- knotlink-0.0.0/setup.py +20 -0
knotlink-0.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: knotlink
|
|
3
|
+
Version: 0.0.0
|
|
4
|
+
Summary: A Py-based client for KnotLink communication
|
|
5
|
+
Author: HXH
|
|
6
|
+
Author-email: 1768224274@qq.com
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# KnotLink 使用教程
|
knotlink-0.0.0/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# KnotLink 使用教程
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# OpenSocketQuerier.py
|
|
2
|
+
# Copyright (C) 2025 HXH
|
|
3
|
+
#
|
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program. If not, see https://www.gnu.org/licenses/
|
|
16
|
+
|
|
17
|
+
from .tcpclient import TcpClient # 确保 tcpclient.py 在同一目录下
|
|
18
|
+
import threading
|
|
19
|
+
|
|
20
|
+
class OpenSocketQuerier:
|
|
21
|
+
def __init__(self, APPID: str, OpenSocketID: str):
|
|
22
|
+
self.appID = APPID
|
|
23
|
+
self.openSocketID = OpenSocketID
|
|
24
|
+
self.callback = None # 用户设置的回调函数
|
|
25
|
+
self.query_result = None # 用于存储同步查询的结果
|
|
26
|
+
self.query_event = threading.Event() # 用于同步查询的事件
|
|
27
|
+
self.is_querying = False # 标记是否正在进行同步查询
|
|
28
|
+
self.init()
|
|
29
|
+
|
|
30
|
+
def init(self):
|
|
31
|
+
self.KLquerier = TcpClient()
|
|
32
|
+
self.KLquerier.connect_to_server("127.0.0.1", 6376)
|
|
33
|
+
self.KLquerier.received_data_callback = self._internal_data_recv # 设置内部数据接收回调
|
|
34
|
+
|
|
35
|
+
def set_config(self, APPID: str, OpenSocketID: str):
|
|
36
|
+
self.appID = APPID
|
|
37
|
+
self.openSocketID = OpenSocketID
|
|
38
|
+
|
|
39
|
+
def query(self, data: str) -> str:
|
|
40
|
+
self.query_result = None # 重置查询结果
|
|
41
|
+
self.query_event.clear() # 重置事件
|
|
42
|
+
self.is_querying = True # 标记开始同步查询
|
|
43
|
+
self._query(self.appID, self.openSocketID, data.encode("utf-8"))
|
|
44
|
+
self.query_event.wait() # 等待事件被触发
|
|
45
|
+
self.is_querying = False # 标记结束同步查询
|
|
46
|
+
return self.query_result
|
|
47
|
+
|
|
48
|
+
def query_async(self, data: str):
|
|
49
|
+
self._query(self.appID, self.openSocketID, data.encode("utf-8"))
|
|
50
|
+
|
|
51
|
+
def _query(self, APPID: str, OpenSocketID: str, data: bytes):
|
|
52
|
+
s_key = f"{APPID}-{OpenSocketID}&*&"
|
|
53
|
+
s_key_bytes = s_key.encode("utf-8")
|
|
54
|
+
s_data = s_key_bytes + data
|
|
55
|
+
self.KLquerier.send_data(s_data)
|
|
56
|
+
|
|
57
|
+
def _internal_data_recv(self, data: bytes):
|
|
58
|
+
received_text = data.decode("utf-8", errors="ignore") # 解码为字符串
|
|
59
|
+
if self.is_querying:
|
|
60
|
+
# 如果正在进行同步查询,保存结果并触发事件
|
|
61
|
+
self.query_result = received_text
|
|
62
|
+
self.query_event.set()
|
|
63
|
+
else:
|
|
64
|
+
# 如果不是同步查询,调用用户设置的回调函数
|
|
65
|
+
if self.callback:
|
|
66
|
+
self.callback(received_text)
|
|
67
|
+
|
|
68
|
+
def set_RecvFunc(self, callback):
|
|
69
|
+
"""
|
|
70
|
+
设置接收到数据后的回调函数。
|
|
71
|
+
:param callback: 回调函数,接收一个 str 类型的参数。
|
|
72
|
+
"""
|
|
73
|
+
self.callback = callback
|
|
74
|
+
|
|
75
|
+
# 示例用法
|
|
76
|
+
if __name__ == "__main__":
|
|
77
|
+
def my_callback(data: str):
|
|
78
|
+
print(f"Callback received data: {data}")
|
|
79
|
+
|
|
80
|
+
querier = OpenSocketQuerier(APPID="0x00000001", OpenSocketID="0x00000002")
|
|
81
|
+
querier.set_RecvFunc(my_callback) # 设置回调函数
|
|
82
|
+
|
|
83
|
+
# 同步查询示例
|
|
84
|
+
result = querier.query("Hello, Server!")
|
|
85
|
+
print(f"Synchronous query result: {result}")
|
|
86
|
+
|
|
87
|
+
import time
|
|
88
|
+
# 异步查询示例
|
|
89
|
+
querier.query_async("Another message")
|
|
90
|
+
time.sleep(60) # 等待一段时间以接收数据
|
|
91
|
+
|
|
92
|
+
querier.KLquerier.disconnect()
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# OpenSocketResponser.py
|
|
2
|
+
# Copyright (C) 2025 HXH
|
|
3
|
+
#
|
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program. If not, see https://www.gnu.org/licenses/
|
|
16
|
+
|
|
17
|
+
from .tcpclient import TcpClient # 确保 tcpclient.py 在同一目录下
|
|
18
|
+
from queue import Queue
|
|
19
|
+
import threading
|
|
20
|
+
import time
|
|
21
|
+
|
|
22
|
+
class OpenSocketResponser:
|
|
23
|
+
def __init__(self, APPID: str, OpenSocketID: str):
|
|
24
|
+
self.appID = APPID
|
|
25
|
+
self.openSocketID = OpenSocketID
|
|
26
|
+
self.recv_func = None # 回调函数(str 类型)
|
|
27
|
+
self.data_queue = Queue() # 线程安全队列
|
|
28
|
+
self.init()
|
|
29
|
+
|
|
30
|
+
def init(self):
|
|
31
|
+
self.KLresponser = TcpClient()
|
|
32
|
+
self.KLresponser.connect_to_server("127.0.0.1", 6378)
|
|
33
|
+
self.KLresponser.received_data_callback = self._internal_data_recv
|
|
34
|
+
|
|
35
|
+
s_key = f"{self.appID}-{self.openSocketID}"
|
|
36
|
+
s_key_bytes = s_key.encode("utf-8") # 转换为 UTF-8 编码的 QByteArray
|
|
37
|
+
self.KLresponser.send_data(s_key_bytes)
|
|
38
|
+
|
|
39
|
+
# 启动一个线程处理队列中的数据
|
|
40
|
+
threading.Thread(target=self._process_queue, daemon=True).start()
|
|
41
|
+
|
|
42
|
+
def sendBack(self, data: str, key: str):
|
|
43
|
+
"""向客户端发送响应数据"""
|
|
44
|
+
s_key = f"{key}&*&"
|
|
45
|
+
s_key_bytes = s_key.encode("utf-8")
|
|
46
|
+
s_data = s_key_bytes + data.encode("utf-8")
|
|
47
|
+
self.KLresponser.send_data(s_data)
|
|
48
|
+
|
|
49
|
+
def _internal_data_recv(self, data: bytes):
|
|
50
|
+
"""内部数据接收处理"""
|
|
51
|
+
try:
|
|
52
|
+
key_end = data.index(b"&*&")
|
|
53
|
+
key = data[:key_end].decode("utf-8")
|
|
54
|
+
payload = data[key_end + 3:] # 跳过 "&*&"
|
|
55
|
+
except (ValueError, UnicodeDecodeError) as e:
|
|
56
|
+
print(f"解析数据失败:{e}")
|
|
57
|
+
return
|
|
58
|
+
|
|
59
|
+
if payload:
|
|
60
|
+
self.data_queue.put((payload.decode("utf-8", errors="ignore"), key))
|
|
61
|
+
|
|
62
|
+
def _process_queue(self):
|
|
63
|
+
"""处理队列中的数据"""
|
|
64
|
+
while True:
|
|
65
|
+
if not self.data_queue.empty():
|
|
66
|
+
payload, key = self.data_queue.get()
|
|
67
|
+
if self.recv_func:
|
|
68
|
+
response = self.recv_func(payload)
|
|
69
|
+
if response is not None:
|
|
70
|
+
self.sendBack(response, key)
|
|
71
|
+
self.data_queue.task_done()
|
|
72
|
+
time.sleep(0.01) # 添加一个小的延时
|
|
73
|
+
|
|
74
|
+
def set_RecvFunc(self, recv_func):
|
|
75
|
+
"""
|
|
76
|
+
设置接收到字符串数据后的处理函数。
|
|
77
|
+
:param recv_func: 处理函数,接收一个参数:str 类型的数据。
|
|
78
|
+
处理函数返回一个 str 类型的响应。
|
|
79
|
+
"""
|
|
80
|
+
self.recv_func = recv_func
|
|
81
|
+
|
|
82
|
+
# 示例用法
|
|
83
|
+
if __name__ == "__main__":
|
|
84
|
+
import time
|
|
85
|
+
def on_received_data(data: str) -> str:
|
|
86
|
+
print(f"接收到字符串数据:{data}")
|
|
87
|
+
time.sleep(5)
|
|
88
|
+
return f"Hello, Client! Your message has been received."
|
|
89
|
+
|
|
90
|
+
responser = OpenSocketResponser("0x00000001", "0x00000002")
|
|
91
|
+
responser.set_RecvFunc(on_received_data)
|
|
92
|
+
|
|
93
|
+
# 模拟运行一段时间
|
|
94
|
+
|
|
95
|
+
time.sleep(60)
|
|
96
|
+
responser.KLresponser.disconnect()
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# SignalSender.py
|
|
2
|
+
# Copyright (C) 2025 HXH
|
|
3
|
+
#
|
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program. If not, see https://www.gnu.org/licenses/
|
|
16
|
+
|
|
17
|
+
from .tcpclient import TcpClient # 确保 tcpclient.py 在同一目录下
|
|
18
|
+
import time
|
|
19
|
+
|
|
20
|
+
class SignalSender:
|
|
21
|
+
def __init__(self, APPID=None, SignalID=None):
|
|
22
|
+
self.appID = APPID
|
|
23
|
+
self.signalID = SignalID
|
|
24
|
+
self.KLsender = TcpClient()
|
|
25
|
+
self.KLsender.connect_to_server("127.0.0.1", 6370)
|
|
26
|
+
|
|
27
|
+
def set_config(self, APPID, SignalID):
|
|
28
|
+
self.appID = APPID
|
|
29
|
+
self.signalID = SignalID
|
|
30
|
+
|
|
31
|
+
def emitt(self, data):
|
|
32
|
+
self._emitt(self.appID, self.signalID, data)
|
|
33
|
+
|
|
34
|
+
def _emitt(self, APPID, SignalID, data):
|
|
35
|
+
if isinstance(data, str):
|
|
36
|
+
data = data.encode('utf-8')
|
|
37
|
+
self.__emitt(APPID, SignalID, data)
|
|
38
|
+
|
|
39
|
+
def __emitt(self, APPID, SignalID, data):
|
|
40
|
+
s_key = f"{APPID}-{SignalID}&*&"
|
|
41
|
+
s_key_bytes = s_key.encode('utf-8')
|
|
42
|
+
s_data = s_key_bytes + data
|
|
43
|
+
self.KLsender.send_data(s_data)
|
|
44
|
+
|
|
45
|
+
# 示例用法
|
|
46
|
+
if __name__ == "__main__":
|
|
47
|
+
signal_sender = SignalSender(APPID="1", SignalID="1")
|
|
48
|
+
signal_sender.emitt("Hello, Server!")
|
|
49
|
+
# 等待一段时间以确保数据发送完成
|
|
50
|
+
time.sleep(10)
|
|
51
|
+
signal_sender.KLsender.disconnect()
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# SignalSubscriber.py
|
|
2
|
+
# Copyright (C) 2025 HXH
|
|
3
|
+
#
|
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program. If not, see https://www.gnu.org/licenses/
|
|
16
|
+
|
|
17
|
+
from .tcpclient import TcpClient # 确保 tcpclient.py 在同一目录下
|
|
18
|
+
|
|
19
|
+
class SignalSubscriber:
|
|
20
|
+
def __init__(self, APPID, SignalID):
|
|
21
|
+
self.appID = APPID
|
|
22
|
+
self.signalID = SignalID
|
|
23
|
+
self.callback = None # 用于存储回调函数
|
|
24
|
+
self.init()
|
|
25
|
+
|
|
26
|
+
def init(self):
|
|
27
|
+
self.KLsubscriber = TcpClient()
|
|
28
|
+
self.KLsubscriber.connect_to_server("127.0.0.1", 6372)
|
|
29
|
+
print("OKK")
|
|
30
|
+
self.KLsubscriber.received_data_callback = self.data_recv # 设置数据接收回调
|
|
31
|
+
s_key = f"{self.appID}-{self.signalID}"
|
|
32
|
+
s_key_bytes = s_key.encode('utf-8')
|
|
33
|
+
self.KLsubscriber.send_data(s_key_bytes)
|
|
34
|
+
|
|
35
|
+
def subscribe(self, APPID, SignalID):
|
|
36
|
+
self.appID = APPID
|
|
37
|
+
self.signalID = SignalID
|
|
38
|
+
s_key = f"{self.appID}-{self.signalID}"
|
|
39
|
+
s_key_bytes = s_key.encode('utf-8')
|
|
40
|
+
self.KLsubscriber.send_data(s_key_bytes)
|
|
41
|
+
|
|
42
|
+
def data_recv(self, data):
|
|
43
|
+
# 将接收到的字节数据解码为字符串
|
|
44
|
+
try:
|
|
45
|
+
received_text = data.decode('utf-8', errors='ignore') # 解码并忽略错误
|
|
46
|
+
except Exception as e:
|
|
47
|
+
print(f"解码失败: {e}")
|
|
48
|
+
received_text = ""
|
|
49
|
+
|
|
50
|
+
# 调用用户设置的回调函数(如果已设置)
|
|
51
|
+
if self.callback:
|
|
52
|
+
self.callback(received_text)
|
|
53
|
+
|
|
54
|
+
def set_RecvFunc(self, callback):
|
|
55
|
+
"""
|
|
56
|
+
设置接收到数据后的回调函数。
|
|
57
|
+
:param callback: 回调函数,接收一个 str 类型的参数。
|
|
58
|
+
"""
|
|
59
|
+
self.callback = callback
|
|
60
|
+
|
|
61
|
+
# 示例用法
|
|
62
|
+
if __name__ == "__main__":
|
|
63
|
+
def my_callback(data: str):
|
|
64
|
+
print(f"Callback received data: {data}")
|
|
65
|
+
|
|
66
|
+
subscriber = SignalSubscriber(APPID="1", SignalID="1")
|
|
67
|
+
subscriber.set_RecvFunc(my_callback) # 设置回调函数
|
|
68
|
+
# 等待一段时间以接收数据
|
|
69
|
+
import time
|
|
70
|
+
time.sleep(60)
|
|
71
|
+
subscriber.KLsubscriber.disconnect()
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Copyright (C) 2025 HXH
|
|
2
|
+
#
|
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
6
|
+
# (at your option) any later version.
|
|
7
|
+
#
|
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11
|
+
# GNU General Public License for more details.
|
|
12
|
+
#
|
|
13
|
+
# You should have received a copy of the GNU General Public License
|
|
14
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/ >.
|
|
15
|
+
|
|
16
|
+
# KnotLinkClient_Py/__init__.py
|
|
17
|
+
from .kludf import *
|
|
18
|
+
from .OpenSocketQuerier import *
|
|
19
|
+
from .OpenSocketResponser import *
|
|
20
|
+
from .SignalSender import *
|
|
21
|
+
from .SignalSubscriber import *
|
|
22
|
+
from .tcpclient import *
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# KLUDF.py
|
|
2
|
+
# Copyright (C) 2025 HXH
|
|
3
|
+
#
|
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program. If not, see https://www.gnu.org/licenses/
|
|
16
|
+
|
|
17
|
+
class KLUDF:
|
|
18
|
+
def __init__(self):
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class KLKVMap(dict):
|
|
23
|
+
def serialize(self):
|
|
24
|
+
"""
|
|
25
|
+
将 KLKVMap 序列化为键值对字符串
|
|
26
|
+
:return: 键值对字符串
|
|
27
|
+
"""
|
|
28
|
+
return ";".join(f"{key}={value}" for key, value in self.items())
|
|
29
|
+
|
|
30
|
+
def deserialize(self, keyValueString):
|
|
31
|
+
"""
|
|
32
|
+
将键值对字符串反序列化为 KLKVMap
|
|
33
|
+
:param keyValueString: 键值对字符串
|
|
34
|
+
"""
|
|
35
|
+
self.clear() # 清空当前映射
|
|
36
|
+
pairs = keyValueString.split(";")
|
|
37
|
+
for pair in pairs:
|
|
38
|
+
keyValue = pair.split("=", maxsplit=1)
|
|
39
|
+
if len(keyValue) == 2:
|
|
40
|
+
self[keyValue[0]] = keyValue[1]
|
|
41
|
+
|
|
42
|
+
def get(self, key , defaultVal = ""):
|
|
43
|
+
"""
|
|
44
|
+
安全地读取键值对
|
|
45
|
+
:param key: 键
|
|
46
|
+
:return: 键对应的值,如果键不存在则返回空字符串
|
|
47
|
+
"""
|
|
48
|
+
return super().get(key, defaultVal)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# 测试代码
|
|
52
|
+
if __name__ == "__main__":
|
|
53
|
+
kv_map = KLKVMap()
|
|
54
|
+
kv_map["key1"] = "value1"
|
|
55
|
+
kv_map["key2"] = "value2"
|
|
56
|
+
|
|
57
|
+
print("序列化前:", kv_map)
|
|
58
|
+
serialized = kv_map.serialize()
|
|
59
|
+
print("序列化后:", serialized)
|
|
60
|
+
|
|
61
|
+
new_kv_map = KLKVMap()
|
|
62
|
+
new_kv_map.deserialize(serialized)
|
|
63
|
+
print("反序列化后:", new_kv_map)
|
|
64
|
+
|
|
65
|
+
print("获取 key1 的值:", new_kv_map.get("key1"))
|
|
66
|
+
print("获取不存在的 key3 的值:", new_kv_map.get("key3"))
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Copyright (C) 2025 HXH
|
|
2
|
+
#
|
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
6
|
+
# (at your option) any later version.
|
|
7
|
+
#
|
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11
|
+
# GNU General Public License for more details.
|
|
12
|
+
#
|
|
13
|
+
# You should have received a copy of the GNU General Public License
|
|
14
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/ >.
|
|
15
|
+
|
|
16
|
+
import socket
|
|
17
|
+
import threading
|
|
18
|
+
import time
|
|
19
|
+
|
|
20
|
+
class TcpClient:
|
|
21
|
+
def __init__(self):
|
|
22
|
+
self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
23
|
+
self.heart_beat_interval = 180 # 设置心跳包发送间隔为180秒(3分钟)
|
|
24
|
+
self.heart_beat_timer = None
|
|
25
|
+
self.connected = False
|
|
26
|
+
self.received_data_callback = None
|
|
27
|
+
|
|
28
|
+
def connect_to_server(self, ip, port):
|
|
29
|
+
try:
|
|
30
|
+
self.tcp_socket.connect((ip, port))
|
|
31
|
+
self.connected = True
|
|
32
|
+
print("连接成功")
|
|
33
|
+
self.start_heart_beat()
|
|
34
|
+
threading.Thread(target=self.receive_data, daemon=True).start()
|
|
35
|
+
except socket.error as e:
|
|
36
|
+
print("连接失败:", e)
|
|
37
|
+
|
|
38
|
+
def start_heart_beat(self):
|
|
39
|
+
self.heart_beat_timer = threading.Timer(self.heart_beat_interval, self.send_heart_beat)
|
|
40
|
+
self.heart_beat_timer.start()
|
|
41
|
+
|
|
42
|
+
def send_heart_beat(self):
|
|
43
|
+
if self.connected:
|
|
44
|
+
try:
|
|
45
|
+
self.tcp_socket.sendall(b"heartbeat")
|
|
46
|
+
print("发送心跳包成功")
|
|
47
|
+
except socket.error as e:
|
|
48
|
+
print("发送心跳包失败:", e)
|
|
49
|
+
self.connected = False
|
|
50
|
+
else:
|
|
51
|
+
print("无法发送心跳包,连接已断开。")
|
|
52
|
+
self.start_heart_beat()
|
|
53
|
+
|
|
54
|
+
def receive_data(self):
|
|
55
|
+
while self.connected:
|
|
56
|
+
try:
|
|
57
|
+
data = self.tcp_socket.recv(1024)
|
|
58
|
+
if not data:
|
|
59
|
+
print("连接已断开")
|
|
60
|
+
self.connected = False
|
|
61
|
+
break
|
|
62
|
+
print("收到数据:", data)
|
|
63
|
+
if data != b"heartbeat_response":
|
|
64
|
+
self.handle_received_data(data)
|
|
65
|
+
except socket.error as e:
|
|
66
|
+
print("接收数据失败:", e)
|
|
67
|
+
self.connected = False
|
|
68
|
+
break
|
|
69
|
+
|
|
70
|
+
def handle_received_data(self, data):
|
|
71
|
+
# 在这里处理接收到的数据
|
|
72
|
+
print("处理数据:", data)
|
|
73
|
+
if self.received_data_callback:
|
|
74
|
+
self.received_data_callback(data)
|
|
75
|
+
|
|
76
|
+
def send_data(self, data):
|
|
77
|
+
if self.connected:
|
|
78
|
+
try:
|
|
79
|
+
self.tcp_socket.sendall(data)
|
|
80
|
+
except socket.error as e:
|
|
81
|
+
print("发送数据失败:", e)
|
|
82
|
+
self.connected = False
|
|
83
|
+
else:
|
|
84
|
+
print("无法发送数据,连接已断开。")
|
|
85
|
+
|
|
86
|
+
def disconnect(self):
|
|
87
|
+
self.connected = False
|
|
88
|
+
self.tcp_socket.close()
|
|
89
|
+
if self.heart_beat_timer:
|
|
90
|
+
self.heart_beat_timer.cancel()
|
|
91
|
+
print("已断开连接")
|
|
92
|
+
|
|
93
|
+
# 示例用法
|
|
94
|
+
if __name__ == "__main__":
|
|
95
|
+
client = TcpClient()
|
|
96
|
+
client.connect_to_server("127.0.0.1", 6370) # 替换为服务器的 IP 和端口
|
|
97
|
+
time.sleep(10) # 等待一段时间
|
|
98
|
+
client.send_data(b"Hello, Server!")
|
|
99
|
+
time.sleep(60) # 继续等待一段时间
|
|
100
|
+
client.disconnect()
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: knotlink
|
|
3
|
+
Version: 0.0.0
|
|
4
|
+
Summary: A Py-based client for KnotLink communication
|
|
5
|
+
Author: HXH
|
|
6
|
+
Author-email: 1768224274@qq.com
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# KnotLink 使用教程
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
setup.py
|
|
3
|
+
knotlink/OpenSocketQuerier.py
|
|
4
|
+
knotlink/OpenSocketResponser.py
|
|
5
|
+
knotlink/SignalSender.py
|
|
6
|
+
knotlink/SignalSubscriber.py
|
|
7
|
+
knotlink/__init__.py
|
|
8
|
+
knotlink/kludf.py
|
|
9
|
+
knotlink/tcpclient.py
|
|
10
|
+
knotlink.egg-info/PKG-INFO
|
|
11
|
+
knotlink.egg-info/SOURCES.txt
|
|
12
|
+
knotlink.egg-info/dependency_links.txt
|
|
13
|
+
knotlink.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
knotlink
|
knotlink-0.0.0/setup.cfg
ADDED
knotlink-0.0.0/setup.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name='knotlink', # 包名
|
|
5
|
+
version='0.0.0', # 版本号
|
|
6
|
+
packages=find_packages(), # 自动发现包和模块
|
|
7
|
+
description='A Py-based client for KnotLink communication', # 简短描述
|
|
8
|
+
long_description=open('README.md', encoding='utf-8').read(), # 从 README.md 读取长描述
|
|
9
|
+
long_description_content_type='text/markdown', # 长描述的格式
|
|
10
|
+
author='HXH', # 作者
|
|
11
|
+
author_email='1768224274@qq.com', # 作者邮箱
|
|
12
|
+
install_requires=[ # 依赖包
|
|
13
|
+
],
|
|
14
|
+
classifiers=[
|
|
15
|
+
'Programming Language :: Python :: 3',
|
|
16
|
+
'Operating System :: OS Independent',
|
|
17
|
+
'Topic :: Software Development :: Libraries :: Python Modules',
|
|
18
|
+
'Intended Audience :: Developers',
|
|
19
|
+
],
|
|
20
|
+
)
|