Added basic server functionality.

parent fc96efa9
......@@ -2,10 +2,12 @@ import asyncore, socket
from Queue import Queue
import re
import random
from asyncbase import AsyncBase
class ClientConnection(object, asyncore.dispatcher):
class ClientConnection(object, AsyncBase, asyncore.dispatcher):
def __init__(self):
AsyncBase.__init__(self)
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
......@@ -19,34 +21,11 @@ class ClientConnection(object, asyncore.dispatcher):
# Generate a random user name
self.user = 'Anonymous' + str(int(random.random()*10000))
# Connection/chat event callbacks
self.event_list = { }
self.send_queue = Queue()
self.send_buffer = ''
def init_loop(self):
"""Initialise the asyncore loop (blocking)."""
# Set a timeout of 0.1 seconds and use poll() when available.
asyncore.loop(.1, True)
def debug_log(self, msg):
if 'debug' in self.event_list:
self.event_list['debug'](self, msg)
else:
print msg
def connect(self, addr):
self.host = addr[0]
self.port = addr[1]
super(ClientConnection, self).connect(addr)
def send_raw(self, cmd):
"""
Send raw command to the chat server.
"""
self.send_queue.put(cmd)
def retrieve_users(self):
"""
Retreive list of users active at the chat server.
......@@ -109,14 +88,6 @@ class ClientConnection(object, asyncore.dispatcher):
else:
self.parse_notification(buf)
def handle_write(self):
if not self.send_buffer:
self.send_buffer = self.send_queue.get()
self.debug_log('> %s' % self.send_buffer)
self.send_buffer += '\r\n'
sent = self.send(self.send_buffer)
self.send_buffer = self.send_buffer[sent:]
def verify_server(self, buf):
match = re.match('^CHAT/(\d\.\d)/([^\x00-\x1F/:]+)$', buf)
......@@ -172,10 +143,6 @@ class ClientConnection(object, asyncore.dispatcher):
elif 'notify' in self.event_list:
self.event_list['notify'](self, buf)
def writable(self):
write = not self.send_queue.empty() or len(self.send_buffer)
return write
if __name__ == '__main__':
client = ClientConnection()
client.connect(('ow150.science.uva.nl', 16897))
......
import asyncore, socket
from Queue import Queue
class AsyncBase(asyncore.dispatcher):
def __init__(self):
self.send_queue = Queue()
self.send_buffer = ''
# Connection/chat event callbacks
self.event_list = { }
def init_loop(self):
"""Initialise the asyncore loop (blocking)."""
# Set a timeout of 0.1 seconds and use poll() when available.
asyncore.loop(.1, True)
def debug_log(self, msg):
if 'debug' in self.event_list:
self.event_list['debug'](self, msg)
else:
print msg
def send_raw(self, cmd):
"""
Send raw command to the chat server.
"""
self.send_queue.put(cmd)
def handle_write(self):
if not self.send_buffer:
self.send_buffer = self.send_queue.get()
self.debug_log('> %s' % self.send_buffer)
self.send_buffer += '\r\n'
sent = self.send(self.send_buffer)
self.send_buffer = self.send_buffer[sent:]
def writable(self):
return not self.send_queue.empty() or len(self.send_buffer)
[loggers]
keys=root,Client,Server
[handlers]
keys=consoleHandler
[formatters]
keys=simpleFormatter
[logger_root]
level=DEBUG
handlers=consoleHandler
[logger_Client]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=0
[logger_Server]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=0
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)
[formatter_simpleFormatter]
format=%(asctime)s %(name)s %(levelname)s: %(message)s
datefmt=%H:%M:%S
#!/usr/bin/env python
import asyncore
import logging
import logging.config
import os
import socket
import sys
from asyncbase import AsyncBase
GREETING_MSG = 'Hi there!'
MAJOR_VERSION = 1
MINOR_VERSION = 0
class Server(asyncore.dispatcher):
"""
Basic server which will listen on an host address and port. The given
handler is used to handle the accepted incoming connections.
"""
def __init__(self, ip, port, handler):
asyncore.dispatcher.__init__(self)
self.ip = ip
self.port = port
self.handler = handler
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind((ip, port))
logging.config.fileConfig('logging.conf')
self.log = logging.getLogger('Server')
self.log.info('waiting for incoming connections on port %s.' % port)
self.listen(5)
self.active_clients = {}
def handle_accept(self):
"""
Handle the incoming connection's request.
"""
# TODO: use threads to handle the incoming connections.
try:
conn, addr = self.accept()
self.log.info('accepted client %s:%d' % addr)
except socket.error:
self.log.warning('warning: server accept() threw an exception.')
return
except TypeError:
self.log.warning('warning: server accept() threw EWOULDBLOCK.')
return
# creates an instance of the handler class to handle the
# request/response on the incoming connection.
self.handler(conn, addr, self)
class RequestHandler(AsyncBase, asyncore.dispatcher):
def __init__(self, conn, address, server):
AsyncBase.__init__(self)
asyncore.dispatcher.__init__(self, conn)
self.address = address
self.server = server
self.log = self.server.log
self.send_welcome_message()
def send_welcome_message(self):
self.send_raw("CHAT/%d.%d/%s" \
% (MAJOR_VERSION, MINOR_VERSION, GREETING_MSG))
def handle_read(self):
buf = ''
# Receive a message from the client.
while True:
chunk = self.recv(1)
if not chunk:
raise RuntimeError('socket connection broken')
elif chunk == '\n' and buf[-1] == '\r':
break
buf += chunk
buf = buf[:-1]
self.debug_log('< %s' % buf)
self.send_positive('Ok')
#self.send_negative('Ok')
def send_positive(self, msg):
self.send_raw('+%s' % msg)
def send_negative(self, msg):
self.send_raw('-%s' % msg)
if __name__ == '__main__':
if len(sys.argv) != 3:
print 'usage: %s HOSTNAME PORT' % sys.argv[0]
sys.exit(-1)
# launch the server on the specified hostname and port.
host = sys.argv[1]
port = int(sys.argv[2])
server = Server(host, port, RequestHandler)
try:
asyncore.loop(timeout=.1, use_poll=True)
except KeyboardInterrupt:
print 'Shutting down the server.'
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment