1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
#!/usr/bin/env python
"""
Chat Server Example
This example demonstrates how to create a very simple telnet-style chat
server that supports many connecting clients.
"""
from optparse import OptionParser
from circuits import Component, Debugger
from circuits.net.events import write
from circuits.net.sockets import TCPServer
__version__ = '0.0.1'
USAGE = '%prog [options]'
VERSION = '%prog v' + __version__
def parse_options():
parser = OptionParser(usage=USAGE, version=VERSION)
parser.add_option(
'-b',
'--bind',
action='store',
type='string',
default='0.0.0.0:8000',
dest='bind',
help='Bind to address:[port]',
)
parser.add_option(
'-d',
'--debug',
action='store_true',
default=False,
dest='debug',
help='Enable debug mode',
)
opts, args = parser.parse_args()
return opts, args
class ChatServer(Component):
def init(self, args, opts):
"""
Initialize our ``ChatServer`` Component.
This uses the convenience ``init`` method which is called after the
component is properly constructed and initialized and passed the
same args and kwargs that were passed during construction.
"""
self.args = args
self.opts = opts
self.clients = {}
if opts.debug:
Debugger().register(self)
if ':' in opts.bind:
address, port = opts.bind.split(':')
port = int(port)
else:
address, port = opts.bind, 8000
bind = (address, port)
TCPServer(bind).register(self)
def broadcast(self, data, exclude=None):
exclude = exclude or []
targets = (sock for sock in self.clients if sock not in exclude)
for target in targets:
self.fire(write(target, data))
def connect(self, sock, host, port):
"""Connect Event -- Triggered for new connecting clients"""
self.clients[sock] = {
'host': sock,
'port': port,
'state': {
'nickname': None,
'registered': False,
},
}
self.fire(write(sock, b'Welcome to the circuits Chat Server!\n'))
self.fire(write(sock, b'Please enter a desired nickname: '))
def disconnect(self, sock):
"""Disconnect Event -- Triggered for disconnecting clients"""
if sock not in self.clients:
return
nickname = self.clients[sock]['state']['nickname']
self.broadcast(
f'!!! {nickname:s} has left !!!\n'.encode(),
exclude=[sock],
)
del self.clients[sock]
def read(self, sock, data):
"""Read Event -- Triggered for when client connections have data"""
data = data.strip().decode('utf-8')
if not self.clients[sock]['state']['registered']:
nickname = data
self.clients[sock]['state']['registered'] = True
self.clients[sock]['state']['nickname'] = nickname
self.broadcast(
f'!!! {nickname:s} has joined !!!\n'.encode(),
exclude=[sock],
)
else:
nickname = self.clients[sock]['state']['nickname']
self.broadcast(
f'<{nickname:s}> {data:s}\n'.encode(),
exclude=[sock],
)
def main():
opts, args = parse_options()
# Configure and "run" the System.
ChatServer(args, opts).run()
if __name__ == '__main__':
main()
|