or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

clients.mdexceptions.mdindex.mdintegration.mdmanagers.mdnamespaces.mdservers.md

servers.mddocs/

0

# Server Classes

1

2

Socket.IO server implementations for handling multiple client connections with support for event-driven architecture, room management, session handling, and horizontal scaling through client managers.

3

4

## Capabilities

5

6

### Server

7

8

A synchronous Socket.IO server that handles multiple client connections, provides event-driven communication, room management, session storage, and integrates with various client managers for scaling.

9

10

```python { .api }

11

class Server:

12

"""

13

Synchronous Socket.IO server with full features.

14

15

Inherits from: BaseServer

16

17

Attributes:

18

manager: Client manager instance for handling connections

19

logger: Logger instance for server events

20

eio: Engine.IO server instance

21

"""

22

23

def __init__(self, client_manager=None, logger=False, serializer='default', json=None,

24

async_handlers=False, always_connect=False, namespaces=None, **kwargs):

25

"""

26

Initialize the server.

27

28

Args:

29

client_manager: Client manager instance (defaults to Manager())

30

logger (bool or Logger): Enable logging or provide custom logger

31

serializer (str): Message serializer ('default', 'pickle', 'msgpack', 'cbor')

32

json (module): Custom JSON module

33

async_handlers (bool): Allow async event handlers in sync server

34

always_connect (bool): Accept all connections without authentication

35

namespaces (list): Allowed namespaces

36

**kwargs: Additional Engine.IO server parameters

37

"""

38

39

def emit(self, event, data=None, to=None, room=None, skip_sid=None, namespace=None, callback=None):

40

"""

41

Emit an event to one or more connected clients.

42

43

Args:

44

event (str): Event name

45

data: Event data to send

46

to (str or list): Target client session ID(s)

47

room (str or list): Target room name(s)

48

skip_sid (str): Skip this client session ID

49

namespace (str): Target namespace

50

callback (callable): Callback function for response

51

52

Raises:

53

DisconnectedError: Target client not connected

54

"""

55

56

def send(self, data, to=None, room=None, skip_sid=None, namespace=None, callback=None):

57

"""

58

Send a message event to one or more connected clients.

59

60

Args:

61

data: Message data to send

62

to (str or list): Target client session ID(s)

63

room (str or list): Target room name(s)

64

skip_sid (str): Skip this client session ID

65

namespace (str): Target namespace

66

callback (callable): Callback function for response

67

68

Raises:

69

DisconnectedError: Target client not connected

70

"""

71

72

def call(self, event, data=None, to=None, sid=None, namespace=None, timeout=60):

73

"""

74

Emit an event and wait for a response from a specific client.

75

76

Args:

77

event (str): Event name

78

data: Event data to send

79

to (str): Target client session ID (deprecated, use sid)

80

sid (str): Target client session ID

81

namespace (str): Target namespace

82

timeout (int): Response timeout in seconds

83

84

Returns:

85

Response data from client

86

87

Raises:

88

TimeoutError: No response received within timeout

89

DisconnectedError: Target client not connected

90

"""

91

92

def enter_room(self, sid, room, namespace=None):

93

"""

94

Add a client to a room.

95

96

Args:

97

sid (str): Client session ID

98

room (str): Room name

99

namespace (str): Target namespace

100

101

Raises:

102

DisconnectedError: Client not connected

103

"""

104

105

def leave_room(self, sid, room, namespace=None):

106

"""

107

Remove a client from a room.

108

109

Args:

110

sid (str): Client session ID

111

room (str): Room name

112

namespace (str): Target namespace

113

114

Raises:

115

DisconnectedError: Client not connected

116

"""

117

118

def close_room(self, room, namespace=None):

119

"""

120

Remove all clients from a room and delete the room.

121

122

Args:

123

room (str): Room name

124

namespace (str): Target namespace

125

"""

126

127

def rooms(self, sid, namespace=None):

128

"""

129

Get the list of rooms a client has joined.

130

131

Args:

132

sid (str): Client session ID

133

namespace (str): Target namespace

134

135

Returns:

136

list: Room names the client has joined

137

138

Raises:

139

DisconnectedError: Client not connected

140

"""

141

142

def get_session(self, sid, namespace=None):

143

"""

144

Get the session data for a client.

145

146

Args:

147

sid (str): Client session ID

148

namespace (str): Target namespace

149

150

Returns:

151

dict: Session data

152

153

Raises:

154

DisconnectedError: Client not connected

155

"""

156

157

def save_session(self, sid, session, namespace=None):

158

"""

159

Save session data for a client.

160

161

Args:

162

sid (str): Client session ID

163

session (dict): Session data to save

164

namespace (str): Target namespace

165

166

Raises:

167

DisconnectedError: Client not connected

168

"""

169

170

def session(self, sid, namespace=None):

171

"""

172

Access client session data with context manager.

173

174

Args:

175

sid (str): Client session ID

176

namespace (str): Target namespace

177

178

Returns:

179

Context manager for session access

180

181

Raises:

182

DisconnectedError: Client not connected

183

"""

184

185

def disconnect(self, sid, namespace=None):

186

"""

187

Disconnect a client.

188

189

Args:

190

sid (str): Client session ID

191

namespace (str): Target namespace

192

193

Raises:

194

DisconnectedError: Client not connected

195

"""

196

197

def start_background_task(self, target, *args, **kwargs):

198

"""

199

Start a background task.

200

201

Args:

202

target (callable): Task function

203

*args: Task arguments

204

**kwargs: Task keyword arguments

205

206

Returns:

207

Task handle

208

"""

209

210

def sleep(self, seconds):

211

"""

212

Sleep for the given number of seconds.

213

214

Args:

215

seconds (float): Sleep duration

216

"""

217

218

def on(self, event, handler=None, namespace=None):

219

"""

220

Register an event handler.

221

222

Args:

223

event (str): Event name

224

handler (callable): Event handler function

225

namespace (str): Target namespace

226

227

Returns:

228

Decorator function if handler not provided

229

"""

230

231

def event(self, event=None, handler=None, namespace=None):

232

"""

233

Decorator to register an event handler.

234

235

Args:

236

event (str, optional): Event name (defaults to function name)

237

handler (callable): Event handler function

238

namespace (str): Target namespace

239

240

Returns:

241

Decorator function

242

"""

243

```

244

245

#### Usage Example

246

247

```python

248

import socketio

249

250

# Create server with Redis manager for scaling

251

redis_manager = socketio.RedisManager('redis://localhost:6379')

252

sio = socketio.Server(client_manager=redis_manager, logger=True)

253

254

# Event handlers

255

@sio.event

256

def connect(sid, environ):

257

print(f'Client {sid} connected')

258

# Add to default room

259

sio.enter_room(sid, 'lobby')

260

sio.emit('welcome', {'message': 'Welcome to the server!'}, room=sid)

261

262

@sio.event

263

def disconnect(sid):

264

print(f'Client {sid} disconnected')

265

266

@sio.event

267

def join_room(sid, data):

268

room = data['room']

269

sio.enter_room(sid, room)

270

sio.emit('status', {'message': f'Joined room {room}'}, room=sid)

271

sio.emit('user_joined', {'sid': sid}, room=room, skip_sid=sid)

272

273

@sio.event

274

def leave_room(sid, data):

275

room = data['room']

276

sio.leave_room(sid, room)

277

sio.emit('user_left', {'sid': sid}, room=room)

278

279

@sio.event

280

def chat_message(sid, data):

281

# Get user session data

282

with sio.session(sid) as session:

283

username = session.get('username', 'Anonymous')

284

285

room = data.get('room', 'lobby')

286

message = {

287

'username': username,

288

'message': data['message'],

289

'timestamp': time.time()

290

}

291

292

# Broadcast to room

293

sio.emit('message', message, room=room)

294

295

@sio.event

296

def set_username(sid, data):

297

# Save username in session

298

with sio.session(sid) as session:

299

session['username'] = data['username']

300

301

sio.emit('username_set', {'success': True}, room=sid)

302

303

@sio.event

304

def get_room_info(sid, data):

305

room = data['room']

306

# Use call to get response

307

try:

308

info = sio.call('room_info_request', {'room': room}, sid=sid, timeout=5)

309

return {'info': info}

310

except socketio.TimeoutError:

311

return {'error': 'Timeout getting room info'}

312

313

# Create WSGI app

314

app = socketio.WSGIApp(sio)

315

```

316

317

### AsyncServer

318

319

Asynchronous Socket.IO server that provides all the capabilities of the synchronous Server but uses coroutines for non-blocking operation in asyncio applications.

320

321

```python { .api }

322

class AsyncServer:

323

"""

324

Asynchronous Socket.IO server for asyncio.

325

326

Inherits from: BaseServer

327

328

Attributes:

329

manager: Async client manager instance

330

logger: Logger instance for server events

331

eio: Engine.IO async server instance

332

"""

333

334

def __init__(self, client_manager=None, logger=False, serializer='default', json=None,

335

always_connect=False, namespaces=None, **kwargs):

336

"""

337

Initialize the async server.

338

339

Args:

340

client_manager: Async client manager instance (defaults to AsyncManager())

341

logger (bool or Logger): Enable logging or provide custom logger

342

serializer (str): Message serializer ('default', 'pickle', 'msgpack', 'cbor')

343

json (module): Custom JSON module

344

always_connect (bool): Accept all connections without authentication

345

namespaces (list): Allowed namespaces

346

**kwargs: Additional Engine.IO server parameters

347

"""

348

349

async def emit(self, event, data=None, to=None, room=None, skip_sid=None, namespace=None, callback=None):

350

"""

351

Emit an event to one or more connected clients.

352

353

Args:

354

event (str): Event name

355

data: Event data to send

356

to (str or list): Target client session ID(s)

357

room (str or list): Target room name(s)

358

skip_sid (str): Skip this client session ID

359

namespace (str): Target namespace

360

callback (coroutine): Async callback function for response

361

362

Raises:

363

DisconnectedError: Target client not connected

364

"""

365

366

async def send(self, data, to=None, room=None, skip_sid=None, namespace=None, callback=None):

367

"""

368

Send a message event to one or more connected clients.

369

370

Args:

371

data: Message data to send

372

to (str or list): Target client session ID(s)

373

room (str or list): Target room name(s)

374

skip_sid (str): Skip this client session ID

375

namespace (str): Target namespace

376

callback (coroutine): Async callback function for response

377

378

Raises:

379

DisconnectedError: Target client not connected

380

"""

381

382

async def call(self, event, data=None, to=None, sid=None, namespace=None, timeout=60):

383

"""

384

Emit an event and wait for a response from a specific client.

385

386

Args:

387

event (str): Event name

388

data: Event data to send

389

to (str): Target client session ID (deprecated, use sid)

390

sid (str): Target client session ID

391

namespace (str): Target namespace

392

timeout (int): Response timeout in seconds

393

394

Returns:

395

Response data from client

396

397

Raises:

398

TimeoutError: No response received within timeout

399

DisconnectedError: Target client not connected

400

"""

401

402

async def enter_room(self, sid, room, namespace=None):

403

"""

404

Add a client to a room.

405

406

Args:

407

sid (str): Client session ID

408

room (str): Room name

409

namespace (str): Target namespace

410

411

Raises:

412

DisconnectedError: Client not connected

413

"""

414

415

async def leave_room(self, sid, room, namespace=None):

416

"""

417

Remove a client from a room.

418

419

Args:

420

sid (str): Client session ID

421

room (str): Room name

422

namespace (str): Target namespace

423

424

Raises:

425

DisconnectedError: Client not connected

426

"""

427

428

async def close_room(self, room, namespace=None):

429

"""

430

Remove all clients from a room and delete the room.

431

432

Args:

433

room (str): Room name

434

namespace (str): Target namespace

435

"""

436

437

async def rooms(self, sid, namespace=None):

438

"""

439

Get the list of rooms a client has joined.

440

441

Args:

442

sid (str): Client session ID

443

namespace (str): Target namespace

444

445

Returns:

446

list: Room names the client has joined

447

448

Raises:

449

DisconnectedError: Client not connected

450

"""

451

452

async def get_session(self, sid, namespace=None):

453

"""

454

Get the session data for a client.

455

456

Args:

457

sid (str): Client session ID

458

namespace (str): Target namespace

459

460

Returns:

461

dict: Session data

462

463

Raises:

464

DisconnectedError: Client not connected

465

"""

466

467

async def save_session(self, sid, session, namespace=None):

468

"""

469

Save session data for a client.

470

471

Args:

472

sid (str): Client session ID

473

session (dict): Session data to save

474

namespace (str): Target namespace

475

476

Raises:

477

DisconnectedError: Client not connected

478

"""

479

480

def session(self, sid, namespace=None):

481

"""

482

Access client session data with async context manager.

483

484

Args:

485

sid (str): Client session ID

486

namespace (str): Target namespace

487

488

Returns:

489

Async context manager for session access

490

491

Raises:

492

DisconnectedError: Client not connected

493

"""

494

495

async def disconnect(self, sid, namespace=None):

496

"""

497

Disconnect a client.

498

499

Args:

500

sid (str): Client session ID

501

namespace (str): Target namespace

502

503

Raises:

504

DisconnectedError: Client not connected

505

"""

506

507

def start_background_task(self, target, *args, **kwargs):

508

"""

509

Start a background task.

510

511

Args:

512

target (coroutine): Async task function

513

*args: Task arguments

514

**kwargs: Task keyword arguments

515

516

Returns:

517

asyncio.Task: Task handle

518

"""

519

520

async def sleep(self, seconds):

521

"""

522

Sleep for the given number of seconds.

523

524

Args:

525

seconds (float): Sleep duration

526

"""

527

528

def on(self, event, handler=None, namespace=None):

529

"""

530

Register an async event handler.

531

532

Args:

533

event (str): Event name

534

handler (coroutine): Async event handler function

535

namespace (str): Target namespace

536

537

Returns:

538

Decorator function if handler not provided

539

"""

540

541

def event(self, event=None, handler=None, namespace=None):

542

"""

543

Decorator to register an async event handler.

544

545

Args:

546

event (str, optional): Event name (defaults to function name)

547

handler (coroutine): Async event handler function

548

namespace (str): Target namespace

549

550

Returns:

551

Decorator function

552

"""

553

```

554

555

#### Usage Example

556

557

```python

558

import asyncio

559

import socketio

560

561

# Create async server with Redis manager

562

redis_manager = socketio.AsyncRedisManager('redis://localhost:6379')

563

sio = socketio.AsyncServer(client_manager=redis_manager, logger=True)

564

565

# Async event handlers

566

@sio.event

567

async def connect(sid, environ):

568

print(f'Client {sid} connected')

569

await sio.enter_room(sid, 'lobby')

570

await sio.emit('welcome', {'message': 'Welcome!'}, room=sid)

571

572

@sio.event

573

async def disconnect(sid):

574

print(f'Client {sid} disconnected')

575

576

@sio.event

577

async def join_room(sid, data):

578

room = data['room']

579

await sio.enter_room(sid, room)

580

await sio.emit('status', {'message': f'Joined {room}'}, room=sid)

581

await sio.emit('user_joined', {'sid': sid}, room=room, skip_sid=sid)

582

583

@sio.event

584

async def chat_message(sid, data):

585

# Access session asynchronously

586

async with sio.session(sid) as session:

587

username = session.get('username', 'Anonymous')

588

589

room = data.get('room', 'lobby')

590

message = {

591

'username': username,

592

'message': data['message'],

593

'timestamp': time.time()

594

}

595

596

# Broadcast to room

597

await sio.emit('message', message, room=room)

598

599

@sio.event

600

async def set_username(sid, data):

601

async with sio.session(sid) as session:

602

session['username'] = data['username']

603

604

await sio.emit('username_set', {'success': True}, room=sid)

605

606

@sio.event

607

async def get_users_in_room(sid, data):

608

room = data['room']

609

610

# Simulate async database lookup

611

await asyncio.sleep(0.1)

612

users = await get_room_users(room) # Your async function

613

614

return {'users': users}

615

616

async def get_room_users(room):

617

# Your async implementation

618

return ['user1', 'user2', 'user3']

619

620

# Create ASGI app

621

app = socketio.ASGIApp(sio)

622

623

# Run with an ASGI server like uvicorn

624

# uvicorn main:app --host 0.0.0.0 --port 5000

625

```

626

627

## Event Handler Patterns

628

629

Both Server and AsyncServer support multiple patterns for event handlers:

630

631

### Function-based Handlers

632

633

```python

634

# Synchronous server

635

sio = socketio.Server()

636

637

@sio.event

638

def connect(sid, environ):

639

print(f'Client {sid} connected')

640

641

# With custom event name

642

@sio.on('custom_event')

643

def handle_custom(sid, data):

644

print(f'Custom event from {sid}: {data}')

645

646

# Async server

647

async_sio = socketio.AsyncServer()

648

649

@async_sio.event

650

async def connect(sid, environ):

651

print(f'Client {sid} connected')

652

await async_sio.emit('welcome', room=sid)

653

```

654

655

### Class-based Handlers (Namespaces)

656

657

```python

658

# Using namespace classes (covered in detail in namespaces.md)

659

class ChatNamespace(socketio.Namespace):

660

def on_connect(self, sid, environ):

661

print(f'Client {sid} connected to chat')

662

663

def on_message(self, sid, data):

664

self.emit('response', data, room=sid)

665

666

sio.register_namespace(ChatNamespace('/chat'))

667

```

668

669

## Session Management

670

671

Both servers provide comprehensive session management:

672

673

```python

674

# Synchronous session management

675

@sio.event

676

def save_user_data(sid, data):

677

# Direct session access

678

sio.save_session(sid, {'user_id': data['user_id'], 'preferences': data['prefs']})

679

680

# Context manager (recommended)

681

with sio.session(sid) as session:

682

session['last_activity'] = time.time()

683

session['status'] = 'active'

684

685

# Asynchronous session management

686

@async_sio.event

687

async def save_user_data(sid, data):

688

# Direct session access

689

await async_sio.save_session(sid, {'user_id': data['user_id']})

690

691

# Async context manager (recommended)

692

async with async_sio.session(sid) as session:

693

session['last_activity'] = time.time()

694

session['status'] = 'active'

695

```