0
# TCP Networking
1
2
TCP client implementations for reliable OSC communication with support for OSC 1.0 and 1.1 protocols, SLIP encoding, connection management, synchronous and asynchronous patterns, and automatic reconnection handling.
3
4
## Capabilities
5
6
### Simple TCP Client
7
8
High-level TCP client with message building helpers and connection management.
9
10
```python { .api }
11
class SimpleTCPClient:
12
"""TCP client with message building helpers."""
13
14
def __init__(self, address: str, port: int, family: socket.AddressFamily = socket.AF_INET,
15
mode: str = "1.1"):
16
"""Initialize TCP client.
17
18
Parameters:
19
- address: Target IP address or hostname
20
- port: Target TCP port number
21
- family: Address family (AF_INET, AF_INET6)
22
- mode: OSC protocol mode ("1.0" or "1.1")
23
"""
24
25
def send_message(self, address: str, value: ArgValue = ""):
26
"""Build and send OSC message.
27
28
Parameters:
29
- address: OSC address pattern string
30
- value: Single argument or list of arguments
31
"""
32
33
def get_messages(self, timeout: int = 30) -> Generator[OscMessage, None, None]:
34
"""Receive and parse OSC messages.
35
36
Parameters:
37
- timeout: Receive timeout in seconds
38
39
Yields:
40
OscMessage objects from received data
41
42
Raises:
43
socket.timeout: If no data received within timeout
44
"""
45
46
def close(self):
47
"""Close TCP connection."""
48
```
49
50
### Basic TCP Client
51
52
Low-level TCP client for sending pre-built messages with context manager support.
53
54
```python { .api }
55
class TCPClient:
56
"""Basic OSC TCP client with context manager support."""
57
58
def __init__(self, address: str, port: int, family: socket.AddressFamily = socket.AF_INET,
59
mode: str = "1.1"):
60
"""Initialize TCP client.
61
62
Parameters:
63
- address: Target IP address or hostname
64
- port: Target TCP port number
65
- family: Address family (AF_INET, AF_INET6)
66
- mode: OSC protocol mode ("1.0" or "1.1")
67
"""
68
69
def send(self, content: Union[OscMessage, OscBundle]):
70
"""Send OSC message or bundle.
71
72
Parameters:
73
- content: OscMessage or OscBundle to transmit
74
75
Raises:
76
OSError: If transmission fails
77
"""
78
79
def receive(self, timeout: int = 30) -> Generator[Union[OscMessage, OscBundle], None, None]:
80
"""Receive and parse OSC messages/bundles.
81
82
Parameters:
83
- timeout: Receive timeout in seconds
84
85
Yields:
86
OscMessage or OscBundle objects from received data
87
88
Raises:
89
socket.timeout: If no data received within timeout
90
"""
91
92
def close(self):
93
"""Close TCP connection."""
94
95
def __enter__(self):
96
"""Context manager entry."""
97
return self
98
99
def __exit__(self, exc_type, exc_val, exc_tb):
100
"""Context manager exit with automatic cleanup."""
101
```
102
103
### Asynchronous TCP Client
104
105
Async TCP client for non-blocking OSC communication with asyncio integration.
106
107
```python { .api }
108
class AsyncTCPClient:
109
"""Asynchronous OSC TCP client."""
110
111
def __init__(self, address: str, port: int, family: socket.AddressFamily = socket.AF_INET,
112
mode: str = "1.1"):
113
"""Initialize async TCP client.
114
115
Parameters:
116
- address: Target IP address or hostname
117
- port: Target TCP port number
118
- family: Address family (AF_INET, AF_INET6)
119
- mode: OSC protocol mode ("1.0" or "1.1")
120
"""
121
122
async def send(self, content: Union[OscMessage, OscBundle]):
123
"""Send OSC message or bundle asynchronously.
124
125
Parameters:
126
- content: OscMessage or OscBundle to transmit
127
128
Raises:
129
OSError: If transmission fails
130
"""
131
132
async def receive(self, timeout: int = 30) -> AsyncGenerator[Union[OscMessage, OscBundle], None]:
133
"""Receive and parse OSC messages/bundles asynchronously.
134
135
Parameters:
136
- timeout: Receive timeout in seconds
137
138
Yields:
139
OscMessage or OscBundle objects from received data
140
141
Raises:
142
asyncio.TimeoutError: If no data received within timeout
143
"""
144
145
async def close(self):
146
"""Close TCP connection asynchronously."""
147
148
async def __aenter__(self):
149
"""Async context manager entry."""
150
return self
151
152
async def __aexit__(self, exc_type, exc_val, exc_tb):
153
"""Async context manager exit with automatic cleanup."""
154
```
155
156
### Async Simple TCP Client
157
158
Async TCP client with message building helpers for high-level async communication.
159
160
```python { .api }
161
class AsyncSimpleTCPClient:
162
"""Async TCP client with message building helpers."""
163
164
def __init__(self, address: str, port: int, family: socket.AddressFamily = socket.AF_INET,
165
mode: str = "1.1"):
166
"""Initialize async simple TCP client.
167
168
Parameters:
169
- address: Target IP address or hostname
170
- port: Target TCP port number
171
- family: Address family (AF_INET, AF_INET6)
172
- mode: OSC protocol mode ("1.0" or "1.1")
173
"""
174
175
async def send_message(self, address: str, value: ArgValue = ""):
176
"""Build and send OSC message asynchronously.
177
178
Parameters:
179
- address: OSC address pattern string
180
- value: Single argument or list of arguments
181
"""
182
183
async def get_messages(self, timeout: int = 30) -> AsyncGenerator[OscMessage, None]:
184
"""Receive and parse OSC messages asynchronously.
185
186
Parameters:
187
- timeout: Receive timeout in seconds
188
189
Yields:
190
OscMessage objects from received data
191
192
Raises:
193
asyncio.TimeoutError: If no data received within timeout
194
"""
195
196
async def close(self):
197
"""Close TCP connection asynchronously."""
198
```
199
200
### Async Dispatcher TCP Client
201
202
Async TCP client with dispatcher for automatic response handling.
203
204
```python { .api }
205
class AsyncDispatchTCPClient:
206
"""Async TCP client with dispatcher for handling responses."""
207
208
dispatcher: Dispatcher # Class-level dispatcher instance
209
210
def __init__(self, address: str, port: int, family: socket.AddressFamily = socket.AF_INET,
211
mode: str = "1.1"):
212
"""Initialize async dispatcher TCP client.
213
214
Parameters:
215
- address: Target IP address or hostname
216
- port: Target TCP port number
217
- family: Address family (AF_INET, AF_INET6)
218
- mode: OSC protocol mode ("1.0" or "1.1")
219
"""
220
221
async def send_message(self, address: str, value: ArgValue = ""):
222
"""Build and send OSC message asynchronously.
223
224
Parameters:
225
- address: OSC address pattern string
226
- value: Single argument or list of arguments
227
"""
228
229
async def handle_messages(self, timeout: int = 30):
230
"""Process received messages with dispatcher asynchronously.
231
232
Parameters:
233
- timeout: Receive timeout in seconds
234
235
Processes incoming messages using the class dispatcher,
236
calling mapped handlers for matching addresses.
237
"""
238
239
async def close(self):
240
"""Close TCP connection asynchronously."""
241
```
242
243
### Protocol Mode Constants
244
245
```python { .api }
246
MODE_1_0: str = "1.0" # OSC 1.0 protocol (size-prefixed messages)
247
MODE_1_1: str = "1.1" # OSC 1.1 protocol (SLIP-encoded messages)
248
```
249
250
## Usage Examples
251
252
### Basic TCP Communication
253
254
```python
255
from pythonosc import tcp_client
256
257
# Create simple TCP client
258
client = tcp_client.SimpleTCPClient("127.0.0.1", 8000)
259
260
try:
261
# Send messages
262
client.send_message("/synth/note", [60, 127])
263
client.send_message("/effect/reverb", 0.3)
264
client.send_message("/transport/play", True)
265
266
# Receive responses
267
for message in client.get_messages(timeout=5):
268
print(f"Response: {message.address} -> {message.params}")
269
270
finally:
271
client.close()
272
```
273
274
### Context Manager Usage
275
276
```python
277
from pythonosc import tcp_client
278
from pythonosc.osc_message_builder import OscMessageBuilder
279
280
# Automatic connection management
281
with tcp_client.TCPClient("192.168.1.100", 9000) as client:
282
# Send pre-built message
283
builder = OscMessageBuilder("/mixer/channel/1/volume")
284
builder.add_arg(0.8)
285
message = builder.build()
286
client.send(message)
287
288
# Receive responses
289
for response in client.receive(timeout=10):
290
if hasattr(response, 'address'): # OscMessage
291
print(f"Message: {response.address} {response.params}")
292
else: # OscBundle
293
print(f"Bundle with {response.num_contents} items")
294
```
295
296
### Protocol Mode Selection
297
298
```python
299
from pythonosc import tcp_client
300
301
# OSC 1.0 mode (size-prefixed messages)
302
client_10 = tcp_client.SimpleTCPClient("127.0.0.1", 8000, mode="1.0")
303
client_10.send_message("/osc10/test", "OSC 1.0 message")
304
305
# OSC 1.1 mode (SLIP-encoded messages) - default
306
client_11 = tcp_client.SimpleTCPClient("127.0.0.1", 8001, mode="1.1")
307
client_11.send_message("/osc11/test", "OSC 1.1 message")
308
309
client_10.close()
310
client_11.close()
311
```
312
313
### Asynchronous Communication
314
315
```python
316
import asyncio
317
from pythonosc import tcp_client
318
319
async def async_communication():
320
# Create async client
321
client = tcp_client.AsyncTCPClient("127.0.0.1", 8000)
322
323
try:
324
# Send message asynchronously
325
await client.send_message("/async/test", ["hello", "world"])
326
327
# Receive messages asynchronously
328
async for message in client.receive(timeout=5):
329
print(f"Async response: {message.address} -> {message.params}")
330
331
finally:
332
await client.close()
333
334
# Run async function
335
asyncio.run(async_communication())
336
```
337
338
### Async Context Manager
339
340
```python
341
import asyncio
342
from pythonosc import tcp_client
343
344
async def async_context_example():
345
async with tcp_client.AsyncTCPClient("127.0.0.1", 8000) as client:
346
# Send multiple messages
347
await client.send_message("/async/start", True)
348
await client.send_message("/async/data", [1, 2, 3, 4, 5])
349
await client.send_message("/async/end", False)
350
351
# Process responses
352
message_count = 0
353
async for message in client.receive(timeout=10):
354
print(f"Message {message_count}: {message.address}")
355
message_count += 1
356
if message_count >= 3: # Stop after 3 messages
357
break
358
359
asyncio.run(async_context_example())
360
```
361
362
### Async Dispatcher Pattern
363
364
```python
365
import asyncio
366
from pythonosc import tcp_client
367
from pythonosc.dispatcher import Dispatcher
368
369
# Set up async response handlers
370
async def handle_async_ack(address, *args):
371
print(f"Async ACK: {address} {args}")
372
373
async def handle_async_data(address, *args):
374
print(f"Async data: {address} {args}")
375
376
async def async_dispatcher_example():
377
# Configure class dispatcher
378
tcp_client.AsyncDispatchTCPClient.dispatcher = Dispatcher()
379
tcp_client.AsyncDispatchTCPClient.dispatcher.map("/ack", handle_async_ack)
380
tcp_client.AsyncDispatchTCPClient.dispatcher.map("/data", handle_async_data)
381
382
# Create dispatcher client
383
client = tcp_client.AsyncDispatchTCPClient("127.0.0.1", 8000)
384
385
try:
386
# Send request
387
await client.send_message("/request/sensor_data", "temperature")
388
389
# Handle responses automatically
390
await client.handle_messages(timeout=5)
391
392
finally:
393
await client.close()
394
395
asyncio.run(async_dispatcher_example())
396
```
397
398
### IPv6 TCP Communication
399
400
```python
401
from pythonosc import tcp_client
402
import socket
403
404
# IPv6 TCP client
405
with tcp_client.TCPClient("::1", 8000, family=socket.AF_INET6) as client:
406
client.send_message("/ipv6/test", "Hello IPv6 TCP")
407
408
for message in client.receive(timeout=5):
409
print(f"IPv6 response: {message.address}")
410
```
411
412
### Error Handling and Reconnection
413
414
```python
415
from pythonosc import tcp_client
416
import time
417
import socket
418
419
def reliable_tcp_communication():
420
client = None
421
max_retries = 3
422
retry_count = 0
423
424
while retry_count < max_retries:
425
try:
426
client = tcp_client.SimpleTCPClient("127.0.0.1", 8000)
427
428
# Send message
429
client.send_message("/reliable/test", retry_count)
430
431
# Try to receive response
432
for message in client.get_messages(timeout=5):
433
print(f"Success: {message.address} {message.params}")
434
return # Success, exit function
435
436
except (socket.error, ConnectionRefusedError, socket.timeout) as e:
437
print(f"Attempt {retry_count + 1} failed: {e}")
438
retry_count += 1
439
440
if client:
441
client.close()
442
client = None
443
444
if retry_count < max_retries:
445
time.sleep(2 ** retry_count) # Exponential backoff
446
447
finally:
448
if client:
449
client.close()
450
451
print("All retry attempts failed")
452
453
reliable_tcp_communication()
454
```
455
456
### Batch Message Sending
457
458
```python
459
from pythonosc import tcp_client
460
from pythonosc.osc_bundle_builder import OscBundleBuilder, IMMEDIATELY
461
462
# Send multiple messages efficiently
463
with tcp_client.TCPClient("127.0.0.1", 8000) as client:
464
# Create bundle for batch sending
465
bundle_builder = OscBundleBuilder(IMMEDIATELY)
466
467
# Add multiple messages
468
for i in range(10):
469
msg_builder = OscMessageBuilder(f"/batch/message/{i}")
470
msg_builder.add_arg(i * 10)
471
msg_builder.add_arg(f"Message {i}")
472
bundle_builder.add_content(msg_builder.build())
473
474
# Send entire batch as single bundle
475
batch_bundle = bundle_builder.build()
476
client.send(batch_bundle)
477
478
print("Sent batch of 10 messages in single bundle")
479
```
480
481
## Types and Imports
482
483
```python { .api }
484
from typing import Union, Generator, AsyncGenerator
485
import socket
486
import asyncio
487
488
from pythonosc.osc_message import OscMessage
489
from pythonosc.osc_bundle import OscBundle
490
from pythonosc.osc_message_builder import ArgValue
491
from pythonosc.dispatcher import Dispatcher
492
```