Browse Source

added server side script

master
myitinos 5 years ago
parent
commit
d25bc1906d
3 changed files with 169 additions and 0 deletions
  1. +53
    -0
      server/ClientConnection.py
  2. +65
    -0
      server/Server.py
  3. +51
    -0
      server/__main__.py

+ 53
- 0
server/ClientConnection.py View File

@ -0,0 +1,53 @@
#!/usr/bin/env python3.7
from Server import Server
class ClientConnection(object):
"""
Client connection object
"""
def __init__(self, server: Server, conn, addr, buffSize=4096, encoding='utf8'):
self.server = server
self.conn = conn
self.addr = addr
self.name = '{}:{}'.format(addr[0], addr[1])
self.buffSize = buffSize
self.encoding = encoding
def serve(self) -> None:
"""
Server this connection and start lisneting for incoming
message
"""
self.send(
'[system] Type \':quit\' to quit this conversation')
while True:
msg = self.recv()
if msg != ':quit' and len(msg) > 0:
self.server.sendToAll(self, msg)
else:
self.send('[system] :goodbye:')
break
self.kill()
def send(self, msg: str, end='\n') -> None:
"""
Wrapper method for socker.send and encode the message to
set encoding
"""
self.conn.send(bytes(msg + end, self.encoding))
def recv(self) -> str:
"""
Wrapper method for socket.recv and decode the message from
set encoding
"""
return self.conn.recv(self.buffSize).decode(self.encoding).split('\n')[0]
def kill(self) -> None:
"""
Close this connection and remove it from server
"""
self.conn.close()
self.server.removeClient(self)

+ 65
- 0
server/Server.py View File

@ -0,0 +1,65 @@
#!/usr/bin/env python3.7
import socket # socket, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR
import logging
import threading
from ClientConnection import ClientConnection
class Server(object):
"""
A simple chat application server
"""
clients = []
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
def __init__(self, host: str, port: int, maxClients=64):
self.host = host
self.port = port
self.soc.bind((host, port))
self.maxClients = maxClients
def run(self) -> None:
"""
Start the server and start to listen for incoming connection
"""
self.soc.listen(self.maxClients)
logging.info('Start listening on {}:{} maximum {} clients'.format(
self.host, self.port, self.maxClients))
while True:
conn, addr = self.soc.accept()
client = ClientConnection(self, conn, addr)
msg = '{}:{} has joined the chat.'.format(
client.addr[0], client.addr[1])
self._announce(msg)
self.clients.append(client)
threading.Thread(target=client.serve).start()
def removeClient(self, client: ClientConnection) -> None:
"""
Remove client from this server list of connected clients
"""
msg = '{}:{} has left the chat.'.format(client.addr[0], client.addr[1])
self.clients.remove(client)
self._announce(msg)
def _announce(self, announcement: str) -> None:
"""
Send announcement from system to all connected clients
"""
msg = '[system] {}'.format(announcement)
logging.info(msg)
for client in self.clients:
client.send(msg)
def sendToAll(self, sender: ClientConnection, msg: str) -> None:
"""
Broadcast message from one client to other clients
"""
msg = '[{}:{}] {}'.format(sender.addr[0], sender.addr[1], msg)
logging.info(msg)
for client in self.clients:
if client != sender:
client.send(msg)

+ 51
- 0
server/__main__.py View File

@ -0,0 +1,51 @@
#!/usr/bin/env python3.7
import logging
from Server import Server
def initLogging(logFileName: str) -> None:
"""
Initialise the logging method
"""
logFormatter = logging.Formatter(
fmt="[%(asctime)s][%(levelname)s] %(message)s",
datefmt='%d-%b-%y %H:%M:%S')
rootLogger = logging.getLogger()
fileHandler = logging.FileHandler(logFileName, mode='a')
fileHandler.setFormatter(logFormatter)
rootLogger.addHandler(fileHandler)
consoleHandler = logging.StreamHandler()
consoleHandler.setFormatter(logFormatter)
rootLogger.addHandler(consoleHandler)
rootLogger.setLevel(logging.INFO)
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('host',
metavar='HOST',
help='IP to listen.',
type=str)
parser.add_argument('port',
metavar='PORT',
help='Port to listen.',
type=int)
parser.add_argument('--logFile',
metavar='LOGPATH',
help='Path to log file, default is log.txt',
type=str,
required=False,
default='log.txt')
args = parser.parse_args()
initLogging(args.logFile)
try:
Server(args.host, args.port).run()
except KeyboardInterrupt:
logging.info('Stopped by user input')

Loading…
Cancel
Save