115 lines
4.5 KiB
Python
115 lines
4.5 KiB
Python
import struct
|
||
import socket
|
||
import time
|
||
from fuadmin import settings
|
||
|
||
class VdesMessagePackaged:
|
||
"""VDES消息打包工具类"""
|
||
def __init__(self, Message, MMSI):
|
||
self.message = Message
|
||
self.MMSI = int(MMSI)
|
||
self.chunk_size = 32755
|
||
self.host = getattr(settings, 'VDES_MONITOR_HOST', 'localhost')
|
||
self.port = getattr(settings, 'VDES_MONITOR_PORT', 8083)
|
||
self.buffer_size = getattr(settings, 'VDES_BUFFER_SIZE', 4096)
|
||
|
||
|
||
def create_tcp_packet(self, packet_type, content):
|
||
"""创建符合VDES TCP协议的报文"""
|
||
# 报文帧头 (4字节)
|
||
header = b'####'
|
||
|
||
# 报文类型 (4字节,大端)
|
||
type_field = struct.pack('>I', packet_type)
|
||
|
||
# 报文长度 (4字节,大端,内容长度)
|
||
length = len(content)
|
||
length_field = struct.pack('>I', length)
|
||
|
||
# 构建完整报文
|
||
packet = header + type_field + length_field + content
|
||
return packet
|
||
|
||
#长消息起始片段
|
||
def long_message_start_frame(self, target_mmsi, send_priority):
|
||
data_type = 0 #数据类型
|
||
target_MMSI = target_mmsi #目标MMSI
|
||
priority = send_priority #优先级
|
||
# 打包为二进制 (大端字节序)
|
||
content = struct.pack('>BIB', data_type, target_MMSI, priority)
|
||
return content
|
||
|
||
#长消息延续片段
|
||
def long_message_middle_frame(self, valid_binary_data):
|
||
data_type = 1 #数据类型
|
||
data = valid_binary_data #有效数据
|
||
# 打包为二进制 (大端字节序)
|
||
content = struct.pack('>B', data_type) + data
|
||
return content
|
||
|
||
#长消息结束片段
|
||
def long_message_end_frame(self):
|
||
data_type = 2 #数据类型
|
||
# 打包为二进制 (大端字节序)
|
||
content = struct.pack('>B', data_type)
|
||
return content
|
||
|
||
def create_message_packet(self, message, target_mmsi, send_priority):
|
||
binary_data = message.encode('utf-8')
|
||
message_frames = []
|
||
if len(binary_data) < 4:
|
||
print("使用短消息,编码后的字节数小于4字节")
|
||
return message_frames
|
||
else:
|
||
print(f"使用长消息编码后的字节数为{len(binary_data)}字节")
|
||
|
||
chunks = [binary_data[i:i+self.chunk_size]
|
||
for i in range(0, len(binary_data), self.chunk_size)]
|
||
# 3. 检查总长度限制
|
||
|
||
if len(binary_data) > 256 * 1024:
|
||
raise ValueError("总数据长度超过256KB限制")
|
||
start_frame = self.long_message_start_frame(target_mmsi, send_priority)
|
||
message_frames.append(self.create_tcp_packet(10, start_frame))
|
||
for chunk in chunks:
|
||
middle_frame = self.long_message_middle_frame(chunk)
|
||
message_frames.append(self.create_tcp_packet(10, middle_frame))
|
||
end_frame = self.long_message_end_frame()
|
||
message_frames.append(self.create_tcp_packet(10, end_frame))
|
||
return message_frames
|
||
|
||
def send_message(self):
|
||
"""启动Socket服务端"""
|
||
Target_MMSI = self.MMSI # 示例目标MMSI
|
||
Send_Priority = 1 # 示例发送优先级
|
||
message = self.message
|
||
message_frames = self.create_message_packet(message, Target_MMSI, Send_Priority)
|
||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
||
try:
|
||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||
sock.connect((self.host, self.port))
|
||
print(f"Socket服务端已启动,监听 {self.host}:{self.port}")
|
||
try:
|
||
for message_frame in message_frames:
|
||
print(f"发送报文: {message_frame.hex()}")
|
||
sock.sendall(message_frame)
|
||
# print("二进制表示:", ' '.join(format(byte, '08b') for byte in message_frame))
|
||
time.sleep(0.5)
|
||
# time.sleep(3)
|
||
|
||
sock.shutdown(socket.SHUT_WR)
|
||
sock.close()
|
||
|
||
except (ConnectionResetError, BrokenPipeError):
|
||
print("客户端断开连接")
|
||
|
||
except KeyboardInterrupt:
|
||
print("\n服务端已停止")
|
||
|
||
except Exception as e:
|
||
print(f"服务端错误: {e}")
|
||
|
||
|
||
|
||
# if __name__ == "__main__":
|
||
# send_message() |