通信模块

本模块提供网络通信功能,用于在通用任务中进行数据传递。

支持 TCP 和 UDP 两种传输协议,所有消息使用 UTF-8 编码。

Important

端口限制: 所有网络通信端口必须在 50000-51000 范围内。

核心功能

TCP 客户端

create_tcp_client(ip, port)

Create TCP client (factory function)

Parameters:
  • ip (str) – Server IP address

  • port (int) – Server port (must be between 50000-51000)

Returns:

TCP client instance (already connected)

Return type:

TCPClient

Raises:

Example:

# Method 1: Using create_tcp_client
client = create_tcp_client("127.0.0.1", 8080)
client.send("Hello Server")
response = client.receive()
print(f"Received: {response}")
client.close()

# Method 2: Using with statement (recommended)
with create_tcp_client("127.0.0.1", 8080) as client:
    client.send("Hello Server")
    response = client.receive()
    print(f"Received: {response}")
class TCPClient(ip, port)

Bases: object

TCP Client class

All messages use UTF-8 encoding. Sends data with 0x03 (x03) as end delimiter appended automatically. Receives data until 0x03 delimiter is encountered.

Parameters:
END_OF_TEXT = b'\x03'
__init__(ip, port)

Initialize TCP client

Parameters:
  • ip (str) – Server IP address

  • port (int) – Server port (must be between 50000-51000)

Raises:

ValueError – If port is not in allowed range (50000-51000)

connect()

Connect to server

Returns:

True if connection successful

Return type:

bool

Raises:

RuntimeError – If connection fails

send(data)

Send data (automatically appends 0x03 delimiter)

Parameters:

data (str) – UTF-8 string to send

Returns:

Number of bytes sent (including delimiter)

Return type:

int

Raises:

RuntimeError – If send fails

receive(timeout=None, buffer_size=4096)

Receive data (until 0x03 delimiter is encountered)

Parameters:
  • timeout (Optional[float]) – Timeout in seconds, None for infinite wait

  • buffer_size (int) – Buffer size for each receive (default 4096 bytes)

Returns:

Received UTF-8 string (without delimiter) None: On timeout or receive failure

Return type:

str

Raises:

RuntimeError – When connection is closed or serious error occurs

close()

Close connection

is_connected()

Check if connection is active

Returns:

True if connected, False if disconnected

Return type:

bool

TCP 服务器

create_tcp_server(port, host='0.0.0.0', message_callback=None)

Create TCP server (factory function)

Parameters:
  • port (int) – Port to listen on (must be between 50000-51000)

  • host (str) – Host address to bind (default 0.0.0.0 listens on all interfaces)

  • message_callback (Optional[Callable[[str, Tuple], str]]) – Message handler callback function Signature: callback(message: str, client_address: tuple) -> response: str If None, echoes messages by default

Returns:

TCP server instance (already started)

Return type:

TCPServer

Raises:

Example:

# Method 1: Default echo mode
server = create_tcp_server(8080)
# Server runs in background, echoing all received messages
# Call server.stop() when done

# Method 2: Custom message handler
def my_handler(msg, addr):
    return f"Processed: {msg}"

server = create_tcp_server(8080, message_callback=my_handler)

# Method 3: Using with statement (recommended)
with create_tcp_server(8080) as server:
    # Server runs in background
    import time
    time.sleep(10)  # Run for 10 seconds
# Automatically closes

# Method 4: Manual send/receive
server = create_tcp_server(8080)
# Wait for clients to connect...
clients = server.get_connected_clients()
if clients:
    # Send to first client
    server.send("Hello Client", clients[0])
    # Receive from first client (10 second timeout)
    msg = server.receive(clients[0], timeout=10.0)
class TCPServer(port, host='0.0.0.0')

Bases: object

TCP Server class

All messages use UTF-8 encoding. Sends data with 0x03 (x03) as end delimiter appended automatically. Receives data until 0x03 delimiter is encountered.

Parameters:
  • port (int) –

  • host (str) –

END_OF_TEXT = b'\x03'
__init__(port, host='0.0.0.0')

Initialize TCP server

Parameters:
  • port (int) – Port to listen on (must be between 50000-51000)

  • host (str) – Host address to bind (default 0.0.0.0 listens on all interfaces)

Raises:

ValueError – If port is not in allowed range (50000-51000)

start(message_callback=None)

Start the server

Parameters:

message_callback (Optional[Callable[[str, Tuple], str]]) – Message handler callback function Signature: callback(message: str, client_address: tuple) -> response: str Return value will be sent as response to client If None, echoes the message back by default

Raises:

RuntimeError – If server fails to start

Example:

def handle_message(msg, addr):
    return f"Server received: {msg}"

server = TCPServer(8080)
server.start(message_callback=handle_message)
send(data, client_address=None)

Send data to specific client (automatically appends 0x03 delimiter)

Parameters:
  • data (str) – UTF-8 string to send

  • client_address (Optional[Tuple]) – Client address, if None sends to all clients

Returns:

Number of bytes sent (including delimiter)

Return type:

int

Raises:

RuntimeError – If send fails

receive(client_address, timeout=None, buffer_size=4096)

Receive data from specific client (until 0x03 delimiter is encountered)

Note: This method blocks and may conflict with automatic handler threads. Recommend using message_callback to handle received messages.

Parameters:
  • client_address (Tuple) – Client address

  • timeout (Optional[float]) – Timeout in seconds, None for infinite wait

  • buffer_size (int) – Buffer size for each receive (default 4096 bytes)

Returns:

Received UTF-8 string (without delimiter) None: On timeout or receive failure

Return type:

str

Raises:

RuntimeError – When client is not connected or serious error occurs

get_connected_clients()

Get list of all connected client addresses

Returns:

List of client addresses

Return type:

list

send_to_all(message)

Send message to all connected clients (broadcast)

Parameters:

message (str) – UTF-8 string to send

Raises:

RuntimeError – If send fails

stop()

Stop the server

is_running()

Check if server is running

Returns:

True if running, False if stopped

Return type:

bool

UDP Socket

create_udp_socket(port, host='0.0.0.0')

Create UDP socket (factory function)

Parameters:
  • port (int) – Port to bind (must be between 50000-51000)

  • host (str) – Host address to bind (default 0.0.0.0 listens on all interfaces)

Returns:

UDP socket instance (already bound)

Return type:

UDPSocket

Raises:

Example:

# Method 1: Basic send/receive
sock = create_udp_socket(50001)

# Send to another UDP endpoint
sock.send("Hello UDP", ("192.168.1.100", 50002))

# Receive data (10 second timeout)
result = sock.receive(timeout=10.0)
if result:
    message, sender_addr = result
    print(f"Received '{message}' from {sender_addr}")

sock.close()

# Method 2: Using with statement (recommended)
with create_udp_socket(50001) as sock:
    sock.send("Hello UDP", ("192.168.1.100", 50002))
    result = sock.receive(timeout=5.0)
    if result:
        message, sender_addr = result
        print(f"Received: {message}")

# Method 3: Broadcast
with create_udp_socket(50001) as sock:
    sock.enable_broadcast()
    sock.send("Broadcast message", ("255.255.255.255", 50002))

# Method 4: Reply to sender
with create_udp_socket(50001) as sock:
    result = sock.receive()
    if result:
        message, sender_addr = result
        # Reply to sender
        sock.send(f"Echo: {message}", sender_addr)
class UDPSocket(port, host='0.0.0.0')

Bases: object

UDP Socket class

All messages use UTF-8 encoding. Supports both unicast and broadcast communication.

Parameters:
  • port (int) –

  • host (str) –

__init__(port, host='0.0.0.0')

Initialize UDP socket

Parameters:
  • port (int) – Port to bind (must be between 50000-51000)

  • host (str) – Host address to bind (default 0.0.0.0 listens on all interfaces)

Raises:

ValueError – If port is not in allowed range (50000-51000)

bind()

Bind socket to port

Raises:

RuntimeError – If bind fails

Return type:

None

send(data, address)

Send data to specified address

Parameters:
  • data (str) – UTF-8 string to send

  • address (Tuple[str, int]) – Tuple of (ip, port)

Returns:

Number of bytes sent

Return type:

int

Raises:
receive(timeout=None, buffer_size=4096)

Receive data from socket

Parameters:
  • timeout (Optional[float]) – Timeout in seconds, None for infinite wait

  • buffer_size (int) – Buffer size for receiving (default 4096 bytes)

Returns:

(message, (sender_ip, sender_port)) None: On timeout or receive failure

Return type:

Tuple[str, Tuple[str, int]]

Raises:

RuntimeError – When socket is not bound or serious error occurs

enable_broadcast()

Enable broadcast mode for the socket

Raises:

RuntimeError – If socket is not initialized

Return type:

None

close()

Close socket

Return type:

None

is_bound()

Check if socket is bound

Returns:

True if bound, False otherwise

Return type:

bool

使用说明

端口限制

所有网络模块(TCP 和 UDP)的端口必须在 50000-51000 范围内:

# ✓ 正确 - 端口在允许范围内
tcp_server = create_tcp_server(50001)
tcp_client = create_tcp_client("127.0.0.1", 50500)
udp_socket = create_udp_socket(51000)

# ✗ 错误 - 端口超出范围,将抛出 ValueError
tcp_server = create_tcp_server(8080)   # ValueError
udp_socket = create_udp_socket(5000)   # ValueError

TCP 协议说明

  • 编码: UTF-8

  • 结束符: \x03 (End of Text)

  • 超时行为: receive() 超时返回 None,不抛出异常

  • 连接模式: 面向连接,可靠传输

UDP 协议说明

  • 编码: UTF-8

  • 无结束符: UDP 是消息边界保留的协议

  • 超时行为: receive() 超时返回 None

  • 连接模式: 无连接,不保证可靠传输

  • 支持广播: 可启用广播模式发送到多个接收者

基本示例

TCP 客户端示例

from daystar_api.tcp_client import create_tcp_client

# 创建客户端并连接(使用 with 语句)
with create_tcp_client("192.168.1.100", 50001) as client:
    # 发送消息
    client.send("Hello Server")

    # 接收响应
    response = client.receive(timeout=5.0)
    if response:
        print(f"Received: {response}")

TCP 服务器示例

from daystar_api.tcp_server import create_tcp_server

# 定义消息处理函数
def handle_message(msg, client_addr):
    print(f"Received from {client_addr}: {msg}")
    return f"Echo: {msg}"

# 创建并启动服务器
server = create_tcp_server(50001, message_callback=handle_message)

# 服务器在后台运行...
# 需要时停止服务器
server.stop()

UDP Socket 基本示例

from daystar_api.udp_socket import create_udp_socket

# 发送方
with create_udp_socket(50001) as sender:
    sender.send("Hello UDP", ("192.168.1.100", 50002))

# 接收方
with create_udp_socket(50002) as receiver:
    result = receiver.receive(timeout=10.0)
    if result:
        message, sender_addr = result
        print(f"Received '{message}' from {sender_addr}")

        # 回复发送者
        receiver.send(f"Echo: {message}", sender_addr)

UDP 广播示例

from daystar_api.udp_socket import create_udp_socket

# 广播发送方
with create_udp_socket(50001) as broadcaster:
    broadcaster.enable_broadcast()
    broadcaster.send("Broadcast message", ("255.255.255.255", 50002))

# 广播接收方(多个实例可同时接收)
with create_udp_socket(50002) as receiver:
    result = receiver.receive(timeout=5.0)
    if result:
        message, sender_addr = result
        print(f"Broadcast received: {message}")

高级用法

TCP 服务器手动发送

server = create_tcp_server(50001)

# 获取所有已连接的客户端
clients = server.get_connected_clients()

# 发送到特定客户端
if clients:
    server.send("Hello Client", clients[0])

# 广播到所有客户端
server.send_to_all("Broadcast message")

UDP 实时通信

import time

with create_udp_socket(50001) as sock:
    # 持续接收并回复
    while True:
        result = sock.receive(timeout=1.0)
        if result:
            message, sender = result
            print(f"Got: {message}")
            sock.send(f"ACK: {message}", sender)

        # 定期发送心跳
        sock.send("heartbeat", ("192.168.1.100", 50002))
        time.sleep(1)

协议选择建议

TCP 适用场景

  • 需要可靠传输的场景

  • 大量数据传输

  • 客户端-服务器架构

  • 需要保证消息顺序

UDP 适用场景

  • 实时性要求高,可容忍少量丢包

  • 广播/组播通信

  • 无状态通信

  • 简单的请求-响应模式

  • 发现和心跳检测

错误处理

所有通信模块的错误处理遵循统一规范:

from daystar_api.tcp_client import create_tcp_client

try:
    # 端口超出范围
    client = create_tcp_client("127.0.0.1", 8080)
except ValueError as e:
    print(f"端口错误: {e}")

try:
    # 连接失败
    client = create_tcp_client("192.168.1.100", 50001)
except RuntimeError as e:
    print(f"连接失败: {e}")

try:
    # 发送失败
    client.send("data")
except RuntimeError as e:
    print(f"发送失败: {e}")