or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

asyncio-client.mdasyncio-server.mddata-structures.mdexceptions.mdextensions.mdindex.mdprotocol.mdrouting.mdsync-client.mdsync-server.md

sync-client.mddocs/

0

# Synchronous Client Operations

1

2

Threading-based synchronous WebSocket client functionality for connecting to WebSocket servers using blocking operations, suitable for traditional Python applications that don't use asyncio.

3

4

## Core Imports

5

6

```python

7

from websockets.sync.client import connect, unix_connect, ClientConnection

8

```

9

10

## Capabilities

11

12

### Connection Functions

13

14

Create synchronous WebSocket client connections with blocking operations for environments where asyncio is not suitable or preferred.

15

16

```python { .api }

17

def connect(

18

uri: str,

19

*,

20

# TCP/TLS

21

sock: socket.socket | None = None,

22

ssl: ssl.SSLContext | None = None,

23

server_hostname: str | None = None,

24

# WebSocket

25

origin: Origin | None = None,

26

extensions: Sequence[ClientExtensionFactory] | None = None,

27

subprotocols: Sequence[Subprotocol] | None = None,

28

compression: str | None = "deflate",

29

# HTTP

30

additional_headers: HeadersLike | None = None,

31

user_agent_header: str | None = USER_AGENT,

32

proxy: str | Literal[True] | None = True,

33

proxy_ssl: ssl.SSLContext | None = None,

34

proxy_server_hostname: str | None = None,

35

# Timeouts

36

open_timeout: float | None = 10,

37

ping_interval: float | None = 20,

38

ping_timeout: float | None = 20,

39

close_timeout: float | None = 10,

40

# Limits

41

max_size: int | None = 2**20,

42

max_queue: int | None | tuple[int | None, int | None] = 16,

43

# Logging

44

logger: LoggerLike | None = None,

45

# Escape hatch for advanced customization

46

create_connection: type[ClientConnection] | None = None,

47

**kwargs: Any

48

) -> ClientConnection:

49

"""

50

Connect to a WebSocket server synchronously.

51

52

Parameters:

53

- uri: WebSocket URI (ws:// or wss://)

54

- sock: Preexisting TCP socket (overrides host/port from URI)

55

- ssl: SSL context for TLS configuration

56

- server_hostname: Host name for TLS handshake (overrides URI hostname)

57

- origin: Value of Origin header for servers that require it

58

- extensions: List of supported extensions in negotiation order

59

- subprotocols: List of supported subprotocols in preference order

60

- compression: Compression mode ("deflate" or None)

61

- additional_headers: Extra HTTP headers for handshake

62

- user_agent_header: Custom User-Agent header

63

- proxy: Proxy configuration (True for auto-detect, str for URL, None to disable)

64

- proxy_ssl: SSL context for proxy connection

65

- proxy_server_hostname: Server hostname for proxy TLS handshake

66

- open_timeout: Timeout for connection establishment (seconds)

67

- ping_interval: Interval between ping frames (seconds)

68

- ping_timeout: Timeout for ping/pong exchange (seconds)

69

- close_timeout: Timeout for connection closure (seconds)

70

- max_size: Maximum message size (bytes)

71

- max_queue: Maximum number of queued messages (int or tuple)

72

- logger: Logger instance for connection logging

73

- create_connection: Custom connection class factory

74

75

Returns:

76

ClientConnection: Synchronous WebSocket connection

77

78

Raises:

79

- InvalidURI: If URI format is invalid

80

- InvalidHandshake: If handshake fails

81

- ConnectionClosedError: If connection fails

82

"""

83

84

def unix_connect(

85

path: str | None = None,

86

uri: str | None = None,

87

**kwargs: Any

88

) -> ClientConnection:

89

"""

90

Connect to a WebSocket server over Unix domain socket synchronously.

91

92

Parameters:

93

- path: Unix socket path for connection (mutually exclusive with uri)

94

- uri: WebSocket URI with unix:// scheme (mutually exclusive with path)

95

- **kwargs: Same keyword arguments as connect()

96

97

Returns:

98

ClientConnection: Synchronous WebSocket connection

99

100

Note:

101

Only available on Unix-like systems (Linux, macOS).

102

Accepts the same keyword arguments as connect().

103

"""

104

```

105

106

### Client Connection Management

107

108

The synchronous ClientConnection class provides blocking operations for WebSocket communication.

109

110

```python { .api }

111

class ClientConnection:

112

"""Synchronous WebSocket client connection."""

113

114

@property

115

def closed(self) -> bool:

116

"""Check if connection is closed."""

117

118

@property

119

def local_address(self) -> Tuple[str, int]:

120

"""Get local socket address."""

121

122

@property

123

def remote_address(self) -> Tuple[str, int]:

124

"""Get remote socket address."""

125

126

@property

127

def subprotocol(self) -> Subprotocol | None:

128

"""Get negotiated subprotocol."""

129

130

def send(self, message: Data, timeout: float = None) -> None:

131

"""

132

Send a message to the WebSocket server.

133

134

Parameters:

135

- message: Text (str) or binary (bytes) message to send

136

- timeout: Optional timeout for send operation (seconds)

137

138

Raises:

139

- ConnectionClosed: If connection is closed

140

- TimeoutError: If timeout is exceeded

141

"""

142

143

def recv(self, timeout: float = None) -> Data:

144

"""

145

Receive a message from the WebSocket server.

146

147

Parameters:

148

- timeout: Optional timeout for receive operation (seconds)

149

150

Returns:

151

str | bytes: Received message (text or binary)

152

153

Raises:

154

- ConnectionClosed: If connection is closed

155

- TimeoutError: If timeout is exceeded

156

"""

157

158

def ping(self, data: bytes = b"", timeout: float = None) -> float:

159

"""

160

Send a ping frame and wait for pong response.

161

162

Parameters:

163

- data: Optional payload for ping frame

164

- timeout: Optional timeout for ping/pong exchange (seconds)

165

166

Returns:

167

float: Round-trip time in seconds

168

169

Raises:

170

- ConnectionClosed: If connection is closed

171

- TimeoutError: If timeout is exceeded

172

"""

173

174

def pong(self, data: bytes = b"") -> None:

175

"""

176

Send a pong frame.

177

178

Parameters:

179

- data: Payload for pong frame

180

181

Raises:

182

- ConnectionClosed: If connection is closed

183

"""

184

185

def close(self, code: int = 1000, reason: str = "") -> None:

186

"""

187

Close the WebSocket connection.

188

189

Parameters:

190

- code: Close code (default 1000 for normal closure)

191

- reason: Human-readable close reason

192

193

Raises:

194

- ProtocolError: If code is invalid

195

"""

196

197

# Context manager support

198

def __enter__(self) -> ClientConnection:

199

"""Enter context manager."""

200

return self

201

202

def __exit__(self, exc_type, exc_value, traceback) -> None:

203

"""Exit context manager and close connection."""

204

self.close()

205

206

# Iterator support for receiving messages

207

def __iter__(self) -> Iterator[Data]:

208

"""Return iterator for receiving messages."""

209

return self

210

211

def __next__(self) -> Data:

212

"""Get next message from iterator."""

213

try:

214

return self.recv()

215

except ConnectionClosed:

216

raise StopIteration

217

```

218

219

## Usage Examples

220

221

### Basic Synchronous Client

222

223

```python

224

from websockets.sync import connect

225

226

def basic_client():

227

"""Simple synchronous WebSocket client."""

228

with connect("ws://localhost:8765") as websocket:

229

# Send a message

230

websocket.send("Hello, Server!")

231

232

# Receive response

233

response = websocket.recv()

234

print(f"Server response: {response}")

235

236

# Run the client

237

basic_client()

238

```

239

240

### Client with Timeout Handling

241

242

```python

243

from websockets.sync import connect

244

from websockets import ConnectionClosed, TimeoutError

245

246

def timeout_client():

247

"""Client with timeout handling."""

248

try:

249

with connect(

250

"ws://localhost:8765",

251

open_timeout=5,

252

close_timeout=3

253

) as websocket:

254

255

# Send with timeout

256

websocket.send("Hello with timeout!", timeout=2.0)

257

258

# Receive with timeout

259

try:

260

response = websocket.recv(timeout=5.0)

261

print(f"Response: {response}")

262

except TimeoutError:

263

print("No response received within timeout")

264

265

# Test connection with ping

266

try:

267

latency = websocket.ping(timeout=3.0)

268

print(f"Connection latency: {latency:.3f}s")

269

except TimeoutError:

270

print("Ping timeout - connection may be stale")

271

272

except ConnectionClosed as e:

273

print(f"Connection closed: {e}")

274

except Exception as e:

275

print(f"Connection error: {e}")

276

277

timeout_client()

278

```

279

280

### Message Iterator Client

281

282

```python

283

from websockets.sync import connect

284

from websockets import ConnectionClosed

285

286

def iterator_client():

287

"""Client using message iteration."""

288

try:

289

with connect("ws://localhost:8765") as websocket:

290

# Send initial message

291

websocket.send("Start streaming")

292

293

# Iterate over received messages

294

for message in websocket:

295

print(f"Received: {message}")

296

297

# Send acknowledgment

298

websocket.send("ACK")

299

300

# Break on specific message

301

if message.lower() == "stop":

302

break

303

304

except ConnectionClosed:

305

print("Connection closed by server")

306

307

iterator_client()

308

```

309

310

### Multi-threaded Client Example

311

312

```python

313

import threading

314

import time

315

from websockets.sync import connect

316

from websockets import ConnectionClosed

317

318

def worker_thread(thread_id: int, uri: str):

319

"""Worker thread with independent WebSocket connection."""

320

try:

321

with connect(uri) as websocket:

322

print(f"Thread {thread_id}: Connected")

323

324

# Send periodic messages

325

for i in range(5):

326

message = f"Thread {thread_id}, Message {i}"

327

websocket.send(message)

328

329

try:

330

response = websocket.recv(timeout=2.0)

331

print(f"Thread {thread_id}: {response}")

332

except Exception as e:

333

print(f"Thread {thread_id}: Error - {e}")

334

335

time.sleep(1)

336

337

except ConnectionClosed as e:

338

print(f"Thread {thread_id}: Connection closed - {e}")

339

340

def multi_threaded_client():

341

"""Example using multiple threads with sync connections."""

342

threads = []

343

uri = "ws://localhost:8765"

344

345

# Create multiple worker threads

346

for i in range(3):

347

thread = threading.Thread(

348

target=worker_thread,

349

args=(i, uri)

350

)

351

threads.append(thread)

352

thread.start()

353

354

# Wait for all threads to complete

355

for thread in threads:

356

thread.join()

357

358

print("All threads completed")

359

360

multi_threaded_client()

361

```

362

363

### Client with Custom Headers and Authentication

364

365

```python

366

from websockets.sync import connect

367

import base64

368

369

def authenticated_client():

370

"""Client with custom headers and authentication."""

371

# Prepare authentication header

372

credentials = base64.b64encode(b"username:password").decode()

373

374

headers = {

375

"Authorization": f"Basic {credentials}",

376

"X-Client-Version": "1.0",

377

"X-Client-Type": "Python-Sync"

378

}

379

380

try:

381

with connect(

382

"ws://localhost:8765",

383

additional_headers=headers,

384

subprotocols=["chat", "notifications"],

385

compression="deflate"

386

) as websocket:

387

388

print(f"Connected with subprotocol: {websocket.subprotocol}")

389

390

# Send authentication verification

391

websocket.send("VERIFY_AUTH")

392

auth_response = websocket.recv()

393

394

if auth_response == "AUTH_OK":

395

print("Authentication successful")

396

397

# Normal operation

398

websocket.send("GET_STATUS")

399

status = websocket.recv()

400

print(f"Status: {status}")

401

else:

402

print("Authentication failed")

403

404

except Exception as e:

405

print(f"Authentication error: {e}")

406

407

authenticated_client()

408

```

409

410

### Unix Domain Socket Client

411

412

```python

413

from websockets.sync import unix_connect

414

415

def unix_client():

416

"""Client connecting via Unix domain socket."""

417

try:

418

with unix_connect("/tmp/websocket.sock") as websocket:

419

print("Connected via Unix socket")

420

421

# Send message

422

websocket.send("Hello via Unix socket!")

423

424

# Receive response

425

response = websocket.recv()

426

print(f"Response: {response}")

427

428

except FileNotFoundError:

429

print("Unix socket not found - is the server running?")

430

except Exception as e:

431

print(f"Unix socket error: {e}")

432

433

unix_client()

434

```

435

436

### Error Handling and Reconnection

437

438

```python

439

import time

440

from websockets.sync import connect

441

from websockets import ConnectionClosed, InvalidURI

442

443

def robust_client_with_reconnect():

444

"""Client with automatic reconnection logic."""

445

uri = "ws://localhost:8765"

446

max_retries = 5

447

retry_delay = 2

448

449

for attempt in range(max_retries):

450

try:

451

print(f"Connection attempt {attempt + 1}")

452

453

with connect(uri, open_timeout=5) as websocket:

454

print("Connected successfully")

455

456

# Normal operation

457

try:

458

while True:

459

websocket.send("ping")

460

response = websocket.recv(timeout=10)

461

462

if response == "pong":

463

print("Connection healthy")

464

time.sleep(5)

465

else:

466

print(f"Unexpected response: {response}")

467

468

except ConnectionClosed:

469

print("Connection lost")

470

break

471

except KeyboardInterrupt:

472

print("Interrupted by user")

473

return

474

475

except (ConnectionClosed, InvalidURI) as e:

476

print(f"Connection failed: {e}")

477

478

if attempt < max_retries - 1:

479

print(f"Retrying in {retry_delay} seconds...")

480

time.sleep(retry_delay)

481

retry_delay *= 2 # Exponential backoff

482

else:

483

print("Max retries exceeded")

484

break

485

486

except Exception as e:

487

print(f"Unexpected error: {e}")

488

break

489

490

robust_client_with_reconnect()

491

```