CSPA Exercise 11: Chat system over tcp with PyQt

PyQt

Task

  • Study the code
    • find out usage of PyQt how; how it is used how it is connected to other components
    • study the usage of coding functionality
  • Find out what can be improved from the code and improve it

Improved Code

uses tcp package

uses util.common

util.common.py

#!/usr/bin/env python
## -*- coding: utf-8 -*-
"""
Common utilities.
"""

##############################################################################
## Uses
import logging
log = logging.getLogger(__name__)

__all__ = list() # python module export list

#############################################################################
## utilities

def buftohex(buf):
  hexseq = str()
  i = 1
  for octet in buf:
    hexseq += "%02x" % ord(str(octet))
    if i % 4 == 0:
      hexseq += " "
    i += 1
  return hexseq
__all__.append("buftohex")

def buftohexstr(buf):
  r = buftohex(buf)
  r += " "
  for octet in buf:
    if ord(octet) >= 0x20 and ord(octet) < 0x7f: # ascii char
      r += octet
    else:
      r += "." 
  return r 
__all__.append("buftohexstr")

def buf_debug(buf):
  r = "DATA(%d) {" % len(buf)
  r += buftohexstr(buf)
  r += "}"
  return r
__all__.append("buf_debug")

#############################################################################
## Testing

import unittest

class Test_utilities(unittest.TestCase):

  def test_buftohex_01(self):
    assert buftohex("testing testing") == "74657374 696e6720 74657374 696e67"

  def test_buftohexstr_01(self):
    #print  buftohexstr("testing testing")
    assert buftohexstr("testing testing") == "74657374 696e6720 74657374 696e67 testing testing"

  def test_buf_debug(self):
    print buf_debug("testing testing")

if __name__ == "__main__":
  logging.basicConfig(level=logging.DEBUG)  
  unittest.main()

exer11.main_client.py

'''
Simple echo client.
'''

import logging
log = logging.getLogger(__name__)
from tcp.interfaces import *
from tcp.tcp_usage import *
import select
import sys
from exer11.interfaces import *
import struct

from PyQt4.QtCore import *
from PyQt4.QtGui import *

from util.common import *
import exer11.codec as codec

#from PySide.QtCore import *
#from PySide.QtGui import *



class ChatUi(QWidget,IUser_ind):
  
  def __init__(self,app,client):
    super(ChatUi,self).__init__(None)
    self.name = "test"
    self.app = app
    self.client = client
    self.client.set_ui(self)
    self.make_layout()
    
  def make_layout(self):
    self.resize(200,200)
    self.setWindowTitle("Chat Client")
    vbox = QVBoxLayout()
    ##
    hbox = QHBoxLayout()
    b = QPushButton("Join")
    b.connect(b,SIGNAL("clicked()"),self.on_join)
    hbox.addWidget(b)
    b = QPushButton("Leave")
    b.connect(b,SIGNAL("clicked()"),self.on_leave)
    hbox.addWidget(b)
    vbox.addLayout(hbox)
    ##
    self.text = QTextEdit()
    self.text.setEnabled(False)
    vbox.addWidget(self.text)
    ##
    self.input = QLineEdit()
    #self.input.setValidator(None)
    self.input.connect(self.input,SIGNAL("returnPressed()"),self.on_return)
    vbox.addWidget(self.input)
    ##
    self.setLayout(vbox)
    self.show()
    
  def run(self):
    log.debug("Running Qt thread ..")
    sys.exit(self.app.exec_())

  def closeEvent(self,event):
    log.debug("Window closing ..")
    self.on_quit()

  def on_quit(self):
    self.app.exit(0)
    self.client.close()

  def on_join(self):
    log.debug("Connect.join()")
    self.client.join("localhost",12345,self.name)
    self.text.append("Joining .. \n")

  def on_leave(self):
    log.debug("Disconnect.leave()")
    self.client.leave(self.name)

  def on_return(self):
    log.debug("Input.returnPressed(): " + self.input.text())
    self.client.send_msg(self.name,str(self.input.text()))
    self.input.clear()
    return None

  def join_ind(self,name):
    self.text.append("*** %s joined" % name)
  
  def leave_ind(self,name):
    self.text.append("*** %s leaved" % name)
    
  def recv_msg(self,name,msg):
    self.text.append("<%s> %s" % (name,msg))

class ChatClient(TCP_conn_ind,IUser_req):
  
  def __init__(self,tcp):
    self.tcp = tcp
    self.ui = None
    self.conn = None
    self.codec = codec.Codec()
    tcp.set_ind(self)

  def set_ui(self,ui):
    self.ui = ui

  def join(self,addr,port,name):
    """
    Join user to chat.
    """
    self.conn = self.tcp.connect("localhost",12345)  
    self.conn.set_ind(self) 
    msg = codec.Join()
    msg.name = name
    self.conn.send(msg.encode())    
  
  def leave(self,name):
    """
    Leave user from chat.
    """
    msg = codec.Leave()
    msg.name = name
    self.conn.send(msg.encode())        
    self.conn.close()  
  
  def send_msg(self,name,chatmsg):
    """
    Send message to chat.
    @param msg: text message. 
    """
    msg = codec.SendMsg()
    msg.name = name
    msg.msg = chatmsg
    log.debug("ChatClient sending %s %s" % (name,chatmsg))
    self.conn.send(msg.encode())        

  def recv(self,data):
    msg = self.codec.decode_data(data)
    if msg.type == 1:
      self.ui.join_ind(msg.name)
    elif msg.type == 2:
      self.ui.leave_ind(msg.name)
    elif msg.type == 3:
      self.ui.recv_msg(msg.name,msg.msg)
    else:
      log.error("Unknown message %d" % type)

  def close(self):
    log.debug("ChatClient.close")    
    self.conn.close()

def run():
  tcp = TCP()
  client = ChatClient(tcp)
  app = QApplication(sys.argv) 
  ui = ChatUi(app,client)
  ## activate
  tcp.start()
  ui.run()

if __name__ == '__main__':
  logging.basicConfig(level=logging.DEBUG)
  run()

exer11.main_server.py

'''
Chat server.
'''

import logging
log = logging.getLogger(__name__)
from tcp.interfaces import *
from tcp.tcp_usage import *
import exer11.codec as codec

class User(TCP_conn_ind):

  def __init__(self,server,conn):
    self.server = server
    self.conn = conn
    self.conn.set_ind(self)
    self.codec = codec.Codec()
  
  def recv(self,data):
    msg = self.codec.decode_data(data)
    if msg.type == 1:
      self.join_recv(msg.name)
    elif msg.type == 2:
      self.leave_recv(msg.name)      
    elif msg.type == 3:
      self.sendmsg_recv(msg.name,msg.msg)    
    else:
      pass
     
  def join_recv(self,name):
    log.debug("Server recv join %s" % name)
    self.server.join(name)

  def leave_recv(self,name):
    log.debug("Server recv leave %s" % name)
    self.server.leave(name)

  def sendmsg_recv(self,name,msg):
    log.debug("Server recv sendmsg %s %s" % (name,msg))
    self.server.sendmsg(name,msg)

  def join_send(self,name):
    msg = codec.Join()
    msg.name = name
    self.conn.send(msg.encode())

  def leave_send(self,name):
    msg = codec.Leave()
    msg.name = name
    self.conn.send(msg.encode())    

  def sendmsg_send(self,name,chatmsg):
    msg = codec.SendMsg()
    msg.name = name
    msg.msg = chatmsg
    self.conn.send(msg.encode())    

  def close(self):
    log.debug("connection closed")
    self.conn.close()
    self.server.remove_user(self)

class Server(TCP_ind):
  
  def __init__(self,tcp):
    self.tcp = tcp
    tcp.set_ind(self)
    self.users = list()

  def join(self,name):
    for user in self.users:
      user.join_send(name)
  
  def leave(self,name):
    for user in self.users:
      user.leave_send(name)

  def sendmsg(self,name,msg):
    for user in self.users:
      user.sendmsg_send(name,msg)

  def new_connection(self,conn):
    log.debug("new connection")
    user = User(self,conn)
    self.users.append(user)
  
  def remove_user(self,user):
    self.users.remove(user)
  
def run():
  tcp = TCP()
  tcp.be_server(12345)
  server = Server(tcp)
  tcp.start()

if __name__ == '__main__':
  logging.basicConfig(level=logging.DEBUG)
  run()

exer11.interfaces.py

'''
Created on Sep 7, 2010

@author: hevi
'''

class IUser_req(object):
  """
  Chat user interaction.
  """

  def join(self,addr,port,name):
    """
    Join user to chat.
    """
    raise NotImplementedError()
  
  def leave(self,name):
    """
    Leave user from chat.
    """
    raise NotImplementedError()
  
  def send_msg(self,name,msg):
    """
    Send message to chat.
    @param msg: text message. 
    """
    raise NotImplementedError()

class IUser_ind(object):

  def join_ind(self,name):
    """
    Join user to chat.
    """
    raise NotImplementedError()
  
  def leave_ind(self,name):
    """
    Leave user from chat.
    """
    raise NotImplementedError()
    
  def recv_msg(self,name,msg):
    """
    Receive message from char.
    @param msg: received text message. 
    """
    raise NotImplementedError()
    
class IService(object):
  """
  Chat service interaction.
  """

  def join(self,user):
    """
    Add user to chat service.
    @param user: user object. 
    """
    raise NotImplementedError()
    
  def leave(self,user):
    """
    Remove user from chat service.
    @param user: user object to remove 
    """
    raise NotImplementedError()    
    
  def send_msg(self,who,msg):
    """
    Broadcast message between users.
    @param who: Where the message originates from.
    @param msg: Chat message.  
    """
    raise NotImplementedError()    

class Message_pdu(object):
  def __init__(self):
    self.type = 0
    self.size = 0    

class Join_pdu(Message_pdu):
  def __init__(self):
    super(Join_pdu,self).__init__()
    self.namesize = 0
    self.name = None

class Leave_pdu(Message_pdu):
  def __init__(self):
    super(Leave_pdu,self).__init__()
    self.namesize = 0
    self.name = None

class SendMsg_pdu(Message_pdu):
  def __init__(self):
    super(SendMsg_pdu,self).__init__()    
    self.namesize = 0
    self.name = None
    self.msgsize = 0
    self.msg = None

exer11.codec.py

"""
Codings for PDU.
"""
import logging
log = logging.getLogger(__name__)
import struct
from exer11.interfaces import *
from util.common import *


class Join(Join_pdu):
  def __init__(self):
    super(Join,self).__init__()

  def encode(self):
    self.type = 1
    self.size = struct.calcsize("HH")
    self.namesize = len(self.name)
    self.size += struct.calcsize("H")
    self.size += self.namesize
    data = str()
    data += struct.pack("HH",self.type,self.size)
    data +=struct.pack("H",self.namesize)
    data += self.name
    log.debug("Join.encode: " + buf_debug(data))
    return data

  def decode(self,data):
    log.debug("Join.decode: " + buf_debug(data))
    hdrsize = struct.calcsize("HH")
    self.type, self.size = struct.unpack("HH",data[0:hdrsize])
    assert self.size == len(data)    
    offset = hdrsize 
    namesizesize = struct.calcsize("H")
    self.namesize, = struct.unpack("H",data[offset:offset + namesizesize])
    offset += namesizesize
    self.name = data[offset:offset+self.namesize]

class Leave(Leave_pdu):
  def __init__(self):
    super(Leave,self).__init__()

  def encode(self):
    self.type = 2
    self.size = struct.calcsize("HH")
    self.namesize = len(self.name)
    self.size += struct.calcsize("H")
    self.size += self.namesize
    data = str()
    data += struct.pack("HH",self.type,self.size)
    data += struct.pack("H",self.namesize)
    data += self.name
    log.debug("Leave.encode: " + buf_debug(data))    
    return data

  def decode(self,data):
    log.debug("Leave.decode: " + buf_debug(data))
    hdrsize = struct.calcsize("HH")
    self.type, self.size = struct.unpack("HH",data[0:hdrsize])
    assert self.size == len(data)
    offset = hdrsize 
    namesizesize = struct.calcsize("H")
    self.namesize, = struct.unpack("H",data[offset:offset + namesizesize])
    offset += namesizesize
    self.name = data[offset:offset+self.namesize]

class SendMsg(SendMsg_pdu):
  def __init__(self):
    super(SendMsg,self).__init__()    

  def encode(self):
    self.type = 3
    self.size = struct.calcsize("HH")
    self.size += struct.calcsize("H")
    self.namesize = len(self.name)
    self.size += self.namesize
    self.size += struct.calcsize("H")    
    self.msgsize = len(self.msg)
    self.size += self.msgsize     
    data = str()
    data += struct.pack("HH",self.type,self.size)
    data += struct.pack("H",self.namesize)
    data += self.name
    data +=struct.pack("H",self.msgsize)
    data += self.msg
    log.debug("SendMsg.encode: " + buf_debug(data))    
    return data
  
  def decode(self,data):
    log.debug("SendMsg.decode: " + buf_debug(data))
    hdrsize = struct.calcsize("HH")
    self.type, self.size = struct.unpack("HH",data[0:hdrsize])
    assert self.size == len(data),"%d vs %d" % (self.size,len(data))
    offset = hdrsize 
    namesizesize = struct.calcsize("H")
    self.namesize, = struct.unpack("H",data[offset:offset + namesizesize])
    offset += namesizesize
    self.name = data[offset:offset+self.namesize]
    offset += self.namesize      
    msgsizesize = struct.calcsize("H")
    self.msgsize, = struct.unpack("H",data[offset:offset + msgsizesize])
    offset += namesizesize      
    self.msg = data[offset:offset+self.msgsize]

class Codec(object):

  def decode_data(self,data):
    ## read common header
    hdrsize = struct.calcsize("HH")
    type, size = struct.unpack("HH",data[0:hdrsize])
    msg = None
    if type == 1:
      msg = Join()
      msg.decode(data)
    elif type == 2:
      msg = Leave()   
      msg.decode(data)         
    elif type == 3:
      msg = SendMsg() 
      msg.decode(data)           
    else:
      log.error("Unknown message %d" % type)
    return msg

exer11.test_codec.py

'''
Test PDU Codec.
'''
import logging
log = logging.getLogger(__name__)
import unittest
import codec

class Test(unittest.TestCase):

  def test_join_01(self):
    emsg = codec.Join()
    emsg.name = "test"
    data = emsg.encode()
    dmsg = codec.Join()
    dmsg.decode(data)
    assert emsg.name == dmsg.name

  def test_leave_01(self):
    emsg = codec.Leave()
    emsg.name = "test"
    data = emsg.encode()
    dmsg = codec.Leave()
    dmsg.decode(data)
    assert emsg.name == dmsg.name

  def test_sendmsg_01(self):
    emsg = codec.SendMsg()
    emsg.name = "test"
    emsg.msg = "message"        
    data = emsg.encode()
    dmsg = codec.SendMsg()
    dmsg.decode(data)
    assert emsg.name == dmsg.name
    assert emsg.msg == dmsg.msg

  def test_join_02(self):
    emsg = codec.Join()
    emsg.name = "test"
    data = emsg.encode()
    c = codec.Codec()
    dmsg = c.decode_data(data)
    assert emsg.name == dmsg.name

  def test_leave_02(self):
    emsg = codec.Leave()
    emsg.name = "test"
    data = emsg.encode()
    c = codec.Codec()
    dmsg = c.decode_data(data)
    assert emsg.name == dmsg.name

  def test_sendmsg_02(self):
    emsg = codec.SendMsg()
    emsg.name = "test"
    emsg.msg = "message"        
    data = emsg.encode()
    c = codec.Codec()
    dmsg = c.decode_data(data)
    assert emsg.name == dmsg.name
    assert emsg.msg == dmsg.msg


if __name__ == "__main__":
  logging.basicConfig(level=logging.DEBUG)  
  unittest.main()

Starting Code

uses tcp package

exer11.main_client.py

'''
Chat Client
'''

import logging
log = logging.getLogger(__name__)
from tcp.interfaces import *
from tcp.tcp_usage import *
import select
from PyQt.QtCore import *
from PyQt.QtGui import *
import sys
from exer11.interfaces import *
import struct

def buftohex(buf):
  hexseq = str()
  for octet in buf:
    hexseq += "%02x" % ord(octet)
  return hexseq


class ChatUi(QWidget,IUser_ind):
  
  def __init__(self,app,client):
    super(ChatUi,self).__init__(None)
    self.name = "test"
    self.app = app
    self.client = client
    self.client.set_ui(self)
    self.make_layout()
    
  def make_layout(self):
    self.resize(200,200)
    self.setWindowTitle("Chat Client")
    vbox = QVBoxLayout()
    ##
    hbox = QHBoxLayout()
    b = QPushButton("Join")
    b.connect(b,SIGNAL("clicked()"),self.on_join)
    hbox.addWidget(b)
    b = QPushButton("Leave")
    b.connect(b,SIGNAL("clicked()"),self.on_leave)
    hbox.addWidget(b)
    vbox.addLayout(hbox)
    ##
    self.text = QTextEdit()
    self.text.setEnabled(False)
    vbox.addWidget(self.text)
    ##
    self.input = QLineEdit()
    self.input.connect(SIGNAL("returnPressed()"),self.on_return)
    vbox.addWidget(self.input)
    ##
    self.setLayout(vbox)
    self.show()
    
  def run(self):
    log.debug("Running Qt thread ..")
    sys.exit(self.app.exec_())

  def closeEvent(self,event):
    log.debug("Window closing ..")
    self.on_quit()

  def on_quit(self):
    self.app.exit(0)
    self.tcp.shutdown()

  def on_join(self):
    log.debug("Connect.join()")
    self.client.join("localhost",12345,self.name)
    self.text.append("Joining .. \n")

  def on_leave(self):
    log.debug("Disconnect.leave()")
    self.client.leave(self.name)

  def on_return(self):
    log.debug("Input.returnPressed(): " + self.input.text())
    self.input.clear()
    self.client.send_msg(self.name,self.input.text())

  def join_ind(self,name):
    self.text.append("*** %s joined" % name)
  
  def leave_ind(self,name):
    self.text.append("*** %s leaved" % name)
    
  def recv_msg(self,name,msg):
    self.text.append("<%s> %s" % (name,msg))

class ChatClient(TCP_conn_ind,IUser_req):
  
  def __init__(self,tcp):
    self.tcp = tcp
    self.ui = None
    self.conn = None
    tcp.set_ind(self)

  def set_ui(self,ui):
    self.ui = ui

  def join(self,addr,port,name):
    """
    Join user to chat.
    """
    self.conn = self.tcp.connect("localhost",12345)  
    self.conn.set_ind(self)
    ## 
    type = 1
    size = struct.calcsize("HH")
    strsize = len(name)
    size += struct.calcsize("H")
    size += strsize
    data = str()
    data += struct.pack("HH",type,size)
    data +=struct.pack("H",strsize)
    data += name
    log.debug("client send join %d %s" % (len(data),buftohex(data)))
    self.conn.send(data)
  
  def leave(self,name):
    """
    Leave user from chat.
    """
    type = 2
    size = struct.calcsize("HH")
    strsize = len(name)
    size += struct.calcsize("H")
    size += strsize
    data = str()
    data += struct.pack("HH",type,size)
    data += struct.pack("H",strsize)
    data += name
    log.debug("client send leave %d %s" % (len(data),buftohex(data)))
    self.conn.send(data)
    self.conn.close()  
  
  def send_msg(self,name,msg):
    """
    Send message to chat.
    @param msg: text message. 
    """
    type = 3
    size = struct.calcsize("HH")
    strsize = len(name)
    size += struct.calcsize("H")
    size += strsize
    msgsize = len(msg)
    size += msgsize     
    data = str()
    data += struct.pack("HH",type,size)
    data +=struct.pack("H",strsize)
    data += name
    data +=struct.pack("H",msgsize)
    data += msg    
    log.debug("client send send_msg %d %s" % (len(data),buftohex(data)))
    self.conn.send(data)

  def recv(self,data):
    ## read common header
    hdrsize = struct.calcsize("HH")
    type, size = struct.unpack("HH",data[0:hdrsize])
    log.debug("recv datasize=%d type=%d size=%d" % (len(data),type,size))    
    offset = hdrsize 
    if type == 1:
      namesizesize = struct.calcsize("H")
      namesize, = struct.unpack("H",data[offset:offset + namesizesize])
      offset += namesizesize
      name = data[offset:offset+namesize]
      self.ui.join_ind(name)
    elif type == 2:
      namesizesize = struct.calcsize("H")
      namesize, = struct.unpack("H",data[offset:offset + namesizesize])
      offset += namesizesize
      name = data[offset:offset+namesize]
      self.ui.leave_ind(name)
    elif type == 3:
      namesizesize = struct.calcsize("H")
      namesize, = struct.unpack("H",data[offset:offset + namesizesize])
      offset += namesizesize
      name = data[offset:offset+namesize]
      offset += namesize      
      msgsizesize = struct.calcsize("H")
      msgsize, = struct.unpack("H",data[offset:offset + msgsizesize])
      offset += namesizesize      
      msg = data[offset:offset+msgsize]
      self.ui.recv_msg(name,msg)
    else:
      log.error("Unknown message %d" % type)

  def close(self):
    log.debug("close")    

def run():
  tcp = TCP()
  client = ChatClient(tcp)
  app = QApplication(sys.argv) 
  ui = ChatUi(app,client)
  ## activate
  tcp.start()
  ui.run()

if __name__ == '__main__':
  logging.basicConfig(level=logging.DEBUG)
  run()

exer11.main_server.py

'''
Simple echo server.
'''

import logging
log = logging.getLogger(__name__)
from tcp.interfaces import *
from tcp.tcp_usage import *
import struct

def buftohex(buf):
  hexseq = str()
  for octet in buf:
    hexseq += "%02x" % ord(octet)
  return hexseq

class User(TCP_conn_ind):

  def __init__(self,server,conn):
    self.server = server
    self.conn = conn
    self.conn.set_ind(self)
  
  def recv(self,data):
    ## read common header
    hdrsize = struct.calcsize("HH")
    type, size = struct.unpack("HH",data[0:hdrsize])
    log.debug("recv datasize=%d type=%d size=%d" % (len(data),type,size))    
    offset = hdrsize 
    if type == 1:
      namesizesize = struct.calcsize("H")
      namesize, = struct.unpack("H",data[offset:offset + namesizesize])
      offset += namesizesize
      name = data[offset:offset+namesize]
      self.join(name)
    elif type == 2:
      namesizesize = struct.calcsize("H")
      namesize, = struct.unpack("H",data[offset:offset + namesizesize])
      offset += namesizesize
      name = data[offset:offset+namesize]
      self.leave(name)
    elif type == 3:
      namesizesize = struct.calcsize("H")
      namesize, = struct.unpack("H",data[offset:offset + namesizesize])
      offset += namesizesize
      name = data[offset:offset+namesize]
      offset += namesize      
      msgsizesize = struct.calcsize("H")
      msgsize, = struct.unpack("H",data[offset:offset + msgsizesize])
      offset += namesizesize      
      msg = data[offset:offset+msgsize]
      self.recv_msg(name,msg)
    else:
      log.error("Unknown message %d" % type)

  def join(self,name):
    log.debug("join %s" % name)
    self.server.join(name)

  def leave(self,name):
    log.debug("leave %s" % name)
    self.server.leave(name)

  def recv_msg(self,name,msg):
    log.debug("recv_msg %s %s" % (name,msg))
    self.server.recv_msg(name,msg)

  def join_send(self,name):
    type = 1
    size = struct.calcsize("HH")
    strsize = len(name)
    size += struct.calcsize("H")
    size += strsize
    data = str()
    data += struct.pack("HH",type,size)
    data +=struct.pack("H",strsize)
    data += name
    log.debug("send %d" % len(data))
    self.conn.send(data)

  def leave_send(self,name):
    type = 2
    size = struct.calcsize("HH")
    strsize = len(name)
    size += struct.calcsize("H")
    size += strsize
    data = str()
    data += struct.pack("HH",type,size)
    data += struct.pack("H",strsize)
    data += name
    self.conn.send(data)

  def send_msg(self,name,msg):
    type = 3
    size = struct.calcsize("HH")
    strsize = len(name)
    size += struct.calcsize("H")
    size += strsize
    msgsize = len(msg)
    size += msgsize     
    data = str()
    data += struct.pack("HH",type,size)
    data +=struct.pack("H",strsize)
    data += name
    data +=struct.pack("H",msgsize)
    data += msg
    log.debug("send: %s %s" % (name,msg))
    self.conn.send(data)

  def close(self):
    log.debug("connection closed")
    self.conn.close()
    self.server.remove_user(self)

class Server(TCP_ind):
  
  def __init__(self,tcp):
    self.tcp = tcp
    tcp.set_ind(self)
    self.users = list()

  def join(self,name):
    for user in self.users:
      user.join_send(name)
  
  def leave(self,name):
    for user in self.users:
      user.leave_send(name)

  def recv_msg(self,name,msg):
    for user in self.users:
      user.send_msg(name,msg)

  def new_connection(self,conn):
    log.debug("new connection")
    user = User(self,conn)
    self.users.append(user)
  
  def remove_user(self,user):
    self.users.remove(user)
  
def run():
  tcp = TCP()
  tcp.be_server(12345)
  server = Server(tcp)
  tcp.start()

if __name__ == '__main__':
  logging.basicConfig(level=logging.DEBUG)
  run()

exer11.interfaces.py

'''
Chat System interfaces
'''

class IUser_req(object):
  """
  Chat user interaction.
  """

  def join(self,addr,port,name):
    """
    Join user to chat.
    """
    raise NotImplementedError()
  
  def leave(self,name):
    """
    Leave user from chat.
    """
    raise NotImplementedError()
  
  def send_msg(self,name,msg):
    """
    Send message to chat.
    @param msg: text message. 
    """
    raise NotImplementedError()

class IUser_ind(object):

  def join_ind(self,name):
    """
    Join user to chat.
    """
    raise NotImplementedError()
  
  def leave_ind(self,name):
    """
    Leave user from chat.
    """
    raise NotImplementedError()
    
  def recv_msg(self,name,msg):
    """
    Receive message from char.
    @param msg: received text message. 
    """
    raise NotImplementedError()
    
class IService(object):
  """
  Chat service interaction.
  """

  def join(self,user):
    """
    Add user to chat service.
    @param user: user object. 
    """
    raise NotImplementedError()
    
  def leave(self,user):
    """
    Remove user from chat service.
    @param user: user object to remove 
    """
    raise NotImplementedError()    
    
  def send_msg(self,who,msg):
    """
    Broadcast message between users.
    @param who: Where the message originates from.
    @param msg: Chat message.  
    """
    raise NotImplementedError()    
Last modified: 2013/07/01 14:42