ソースを参照

a step back to use CLI again

master
myitinos 5年前
コミット
aa37cc0aff
6個のファイルの変更93行の追加91行の削除
  1. +6
    -1
      client/ChatConnection.py
  2. +35
    -68
      client/ChatInterface.py
  3. +10
    -1
      client/__main__.py
  4. +30
    -9
      server/ClientConnection.py
  5. +10
    -10
      server/Server.py
  6. +2
    -2
      server/__main__.py

+ 6
- 1
client/ChatConnection.py ファイルの表示

@ -8,13 +8,17 @@ class ChatConnection(object):
self.soc.connect((host, port))
self.buffSize = buffSize
self.encoding = encoding
self.isOpen = True
def send(self, msg: str) -> None:
"""
Wrapper method of socket.send and encode the message
to set character encoding.
"""
self.soc.send(bytes(msg, self.encoding))
try:
self.soc.send(bytes(msg, self.encoding))
except OSError:
self.close()
def recv(self) -> str:
"""
@ -28,3 +32,4 @@ class ChatConnection(object):
Wrapper method to close the socket
"""
self.soc.close()
self.isOpen = False

+ 35
- 68
client/ChatInterface.py ファイルの表示

@ -1,94 +1,61 @@
#!/usr/bin/env python3.7
import tkinter
import threading
from ChatConnection import ChatConnection
class ChatInterface(object):
def __init__(self, connection: ChatConnection):
def __init__(self,
connection: ChatConnection,
name: str = '<anonymous>'):
# set connection to use
self.connection = connection
self.name = name
# initialise tkinter window
self.window = tkinter.Tk()
self.window.title("Chatter") # window title
# set method to trigger when window is close
self.window.protocol("WM_DELETE_WINDOW", self.close)
# end of window initialisation
# initialise message frame
self.messagesFrame = tkinter.Frame(self.window)
# # add scrollBar to see previously recovered messages
self.scrollBar = tkinter.Scrollbar(self.messagesFrame)
self.scrollBar.pack(side=tkinter.RIGHT, fill=tkinter.Y)
# # add messagesList to print recovered messages
self.messagesList = tkinter.Listbox(
self.messagesFrame, height=15, width=50, yscrollcommand=self.scrollBar.set)
self.messagesList.pack(side=tkinter.LEFT, fill=tkinter.BOTH)
self.messagesList.pack()
self.messagesFrame.pack()
# end of message frame initialisation
# initialise input
self.input = tkinter.StringVar()
self.input.set("Type your messages here.")
# # initialise input frame
self.inputFrame = tkinter.Entry(self.window, textvariable=self.input)
self.inputFrame.bind("<Return>", self.send)
self.inputFrame.pack()
# # initialise send button
self.sendButton = tkinter.Button(
self.window, text="Send", command=self.send)
self.sendButton.pack()
# end of input initialisation
def close(self, event=None) -> None:
"""
Set input to ':quit' and trigger send method
"""
self.input.set(":quit")
self.send()
def send(self, event=None) -> None:
def send(self, msg) -> None:
"""
Send message to connection
"""
msg = self.input.get()
self.connection.send(msg)
# check if input is quit command
if msg != ':quit':
# clear the input bar
self.input.set('')
# output the client message to message list
self.messagesList.insert(tkinter.END, '[YOU] {}'.format(msg))
# send the message to connection
self.connection.send(msg)
else:
# close the connection and window
self.connection.close()
self.window.quit()
if self.connection.isOpen:
if msg[0] == '/':
cmd = msg[1:5]
if cmd == 'quit':
self.connection.close()
elif cmd == 'name':
tmp = msg.split()
if len(tmp) == 2:
self.name = tmp[1]
def listener(self) -> None:
"""
Listener method to keep receiving new message from
connection
"""
while True:
try:
# receive messages from connection
msg = self.connection.recv()
# add recevied message to message list
self.messagesList.insert(tkinter.END, msg[:-1])
except OSError:
break
while self.connection.isOpen:
# receive messages from connection
msg = self.connection.recv()
if len(msg) > 0:
# add recevied message to message list
print('\r' +
msg +
'\n' +
'[ME({})]: '.format(self.name), end='')
else:
self.connection.close()
def start(self) -> None:
"""
Start background listener and tkinter.mainloop
"""
# initialise background listener as daemon thread
backgroundListener = threading.Thread(target=self.listener)
backgroundListener.daemon = True
backgroundListener.start()
# start tkinter main loop and open the GUI window
tkinter.mainloop()
self.send('/name {}'.format(self.name))
while self.connection.isOpen:
try:
msg = input('[ME({})]: '.format(self.name))
except (EOFError, KeyboardInterrupt):
msg = '/quit'
finally:
self.send(msg)

+ 10
- 1
client/__main__.py ファイルの表示

@ -15,6 +15,15 @@ if __name__ == "__main__":
metavar="PORT",
help='Host PORT to connect to.',
type=int)
parser.add_argument("--name",
metavar="NAME",
help='Name you want to be identified as.',
default='<anonymous>',
type=str)
args = parser.parse_args()
ChatInterface(ChatConnection(args.host, args.port)).start()
try:
ChatInterface(ChatConnection(args.host, args.port),
name=args.name).start()
except ConnectionRefusedError as e:
print(e)

+ 30
- 9
server/ClientConnection.py ファイルの表示

@ -1,5 +1,5 @@
#!/usr/bin/env python3.7
from Server import Server
import Server
class ClientConnection(object):
@ -10,28 +10,49 @@ class ClientConnection(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.addr = '{}:{}'.format(addr[0], addr[1])
self.name = '<anonymous>'
self.buffSize = buffSize
self.encoding = encoding
def nameFormat(self):
return '[{}({})]'.format(self.name, self.addr)
def serve(self) -> None:
"""
Server this connection and start lisneting for incoming
Serve this connection and start listening for incoming
message
"""
self.send(
'[system] Type \':quit\' to quit this conversation')
'[system] You are logged in as [{}({})]\n'.format(self.name, self.addr) +
'[system] Type \'/quit\' to quit this conversation\n' +
'[system] Type \'/name <new name>\' to change your name')
while True:
msg = self.recv()
if msg != ':quit' and len(msg) > 0:
self.server.sendToAll(self, msg)
if len(msg) > 0:
if msg[0] == '/':
cmd = msg[1:5]
if cmd == 'quit':
self.send('[system] :goodbye:')
break
elif cmd == 'name':
tmp = msg.split()
if len(tmp) == 2:
self.server.sendToAll(
self,
"changed name to {}".format(tmp[1]))
self.name = tmp[1]
else:
self.send('[system] whitespace are not allowed')
else:
self.send('[system] unrecognised command')
else:
self.server.sendToAll(self, msg)
else:
self.send('[system] :goodbye:')
break
self.kill()
def send(self, msg: str, end='\n') -> None:
def send(self, msg: str, end='') -> None:
"""
Wrapper method for socker.send and encode the message to
set encoding

+ 10
- 10
server/Server.py ファイルの表示

@ -2,8 +2,7 @@
import socket # socket, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR
import logging
import threading
from ClientConnection import ClientConnection
import ClientConnection
class Server(object):
@ -30,18 +29,19 @@ class Server(object):
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])
client = ClientConnection.ClientConnection(self, conn, addr)
msg = '{} has joined the chat.'.format(client.addr)
self._announce(msg)
self.clients.append(client)
threading.Thread(target=client.serve).start()
t = threading.Thread(target=client.serve)
t.daemon = True
t.start()
def removeClient(self, client: ClientConnection) -> None:
def removeClient(self, client: ClientConnection.ClientConnection) -> None:
"""
Remove client from this server list of connected clients
"""
msg = '{}:{} has left the chat.'.format(client.addr[0], client.addr[1])
msg = '{} has left the chat.'.format(client.nameFormat())
self.clients.remove(client)
self._announce(msg)
@ -54,11 +54,11 @@ class Server(object):
for client in self.clients:
client.send(msg)
def sendToAll(self, sender: ClientConnection, msg: str) -> None:
def sendToAll(self, sender: ClientConnection.ClientConnection, msg: str) -> None:
"""
Broadcast message from one client to other clients
"""
msg = '[{}:{}] {}'.format(sender.addr[0], sender.addr[1], msg)
msg = '{} {}'.format(sender.nameFormat(), msg)
logging.info(msg)
for client in self.clients:
if client != sender:

+ 2
- 2
server/__main__.py ファイルの表示

@ -1,6 +1,6 @@
#!/usr/bin/env python3.7
import logging
from Server import Server
import Server
def initLogging(logFileName: str) -> None:
@ -46,6 +46,6 @@ if __name__ == "__main__":
initLogging(args.logFile)
try:
Server(args.host, args.port).run()
Server.Server(args.host, args.port).run()
except KeyboardInterrupt:
logging.info('Stopped by user input')

読み込み中…
キャンセル
保存