Skip to content
Snippets Groups Projects
Commit 4a67180c authored by Sander Mathijs van Veen's avatar Sander Mathijs van Veen
Browse files

Added basic server functionality.

parent fc96efa9
No related branches found
No related tags found
No related merge requests found
......@@ -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.'
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment