| name | pywayne-cross-comm |
| description | WebSocket-based cross-language communication service with support for multiple message types (text, JSON, dict, bytes, images, files, folders) and client management. Use when building real-time communication applications between Python and other languages, needing multi-device messaging, or requiring file transfer via Aliyun OSS. Supports both server and client roles with heartbeat, client list management, and message filtering by type or sender. |
Pywayne Cross Comm
pywayne.cross_comm.CrossCommService provides WebSocket-based real-time communication between Python and other languages, with built-in file transfer via Aliyun OSS.
Prerequisites
OSS Configuration (required for file/image/folder transfer):
File transfers use Aliyun OSS. Set these environment variables:
OSS_ENDPOINT=your-oss-endpoint
OSS_BUCKET_NAME=your-bucket-name
OSS_ACCESS_KEY_ID=your-access-key
OSS_ACCESS_KEY_SECRET=your-access-secret
For more OSS details, see pywayne-aliyun-oss skill.
Quick Start
import asyncio
from pywayne.cross_comm import CrossCommService, CommMsgType
server = CrossCommService(role='server', ip='0.0.0.0', port=9898)
await server.start_server()
client = CrossCommService(role='client', ip='localhost', port=9898, client_id='my_client')
await client.login()
Server
Initialize server
server = CrossCommService(
role='server',
ip='0.0.0.0',
port=9898,
heartbeat_interval=30,
heartbeat_timeout=60
)
Register message listeners
@server.message_listener(msg_type=CommMsgType.TEXT)
async def handle_text(message):
print(f"From {message.from_client_id}: {message.content}")
@server.message_listener(msg_type=CommMsgType.FILE, download_directory="./downloads")
async def handle_file(message):
print(f"File downloaded: {message.content}")
Start server
await server.start_server()
Get online clients
online_clients = server.get_online_clients()
Client
Initialize client
client = CrossCommService(
role='client',
ip='localhost',
port=9898,
client_id='my_client',
heartbeat_interval=30,
heartbeat_timeout=60
)
Login and logout
success = await client.login()
if success:
print("Connected!")
await client.logout()
Send messages
await client.send_message("Hello!", CommMsgType.TEXT)
await client.send_message("Private", CommMsgType.TEXT, to_client_id='target_id')
await client.send_message('{"key": "value"}', CommMsgType.JSON)
await client.send_message({"type": "data", "value": 123}, CommMsgType.DICT)
await client.send_message(b"binary", CommMsgType.BYTES)
await client.send_message("/path/to/file.txt", CommMsgType.FILE)
await client.send_message("/path/to/image.jpg", CommMsgType.IMAGE)
await client.send_message("/path/to/folder", CommMsgType.FOLDER)
Get client list
all_clients = await client.list_clients(only_show_online=False)
online = await client.list_clients(only_show_online=True)
Message Types
CommMsgType enum (use these, not strings):
| Type | Description |
|---|
CommMsgType.TEXT | Plain text |
CommMsgType.JSON | JSON string |
CommMsgType.DICT | Python dict |
CommMsgType.BYTES | Binary data |
CommMsgType.IMAGE | Image file |
CommMsgType.FILE | Regular file |
CommMsgType.FOLDER | Folder |
Internal types (auto-handled): HEARTBEAT, LOGIN, LOGOUT, LIST_CLIENTS, LIST_CLIENTS_RESPONSE, LOGIN_RESPONSE
Message Listener Decorator
@service.message_listener(msg_type=CommMsgType.TEXT)
async def handler(message):
pass
@service.message_listener(msg_type=CommMsgType.FILE, from_client_id='specific_client')
async def handler(message):
pass
@service.message_listener()
async def handler(message):
pass
Note: Listeners automatically filter out messages sent by yourself.
File Download Control
File downloads are controlled via the listener's download_directory parameter:
@client.message_listener(msg_type=CommMsgType.FILE, download_directory="./downloads")
async def handle_file(message):
print(f"Downloaded: {message.content}")
@client.message_listener(msg_type=CommMsgType.FILE, from_client_id='low_priority')
async def handle_file(message):
print(f"File available: {message.oss_key}")
Manual download
success = client.download_file_manually(
oss_key="cross_comm/sender_id/123456_file.txt",
save_directory="./downloads"
)
Message Object
@dataclass
class Message:
msg_id: str
from_client_id: str
to_client_id: str
msg_type: CommMsgType
content: Any
timestamp: float
oss_key: Optional[str]
def to_dict(self) -> Dict:
@classmethod
def from_dict(cls, data) -> 'Message':
Client ID Generation
If client_id is not specified, it's auto-generated using MAC address + UUID:
- Format:
{mac_address}_{uuid_suffix}
- Example:
a1b2c3d4e5f6_abc12345
Command Line
python -m pywayne.cross_comm server
python -m pywayne.cross_comm client
Important Notes
- File transfer: Requires OSS environment variables; files auto-upload on send
- Async required: All operations are async; use
asyncio.run() or await in async context
- Heartbeat: Auto-managed; adjust intervals for network conditions
- Message filtering: Use
download_directory to control auto-downloads and save bandwidth
- State persistence: Server saves client status to
cross_comm_clients.yaml
- Role-specific methods: Server has
start_server(), get_online_clients(); client has login(), logout(), send_message(), list_clients()