-
Notifications
You must be signed in to change notification settings - Fork 0
/
client.py
121 lines (109 loc) · 3.36 KB
/
client.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!usr/bin/env python3
import socket
import sys
import command_parser as parser
import json
import threading
import datetime
HOST = "127.0.0.1"
PORT = 8080
# userDict is a global dictionary tracking the nick associated with this client process
userDict = {"nick": None}
# threading event used for concurrent handling of output to the console
e = threading.Event()
def buildPacket(argsDict):
"""
Build a command packet and convert to JSON object to send to server
"""
command = argsDict.get("command")
if userDict["nick"] == None or command == "user":
nick = argsDict.get("nick")
userDict["nick"] = nick
nick = userDict["nick"]
argsDict["nick"] = nick
if not command or not nick:
return None
else:
return json.dumps(argsDict)
def establishConn():
"""
Establish connection to server and initiate client threads of control
"""
sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
try:
sock.connect((HOST, PORT))
receiver = threading.Thread(target=recvDaemon, args=[sock])
client = threading.Thread(target=clientProcess, args=[receiver])
receiver.start()
client.start()
except ConnectionRefusedError:
print("Error: could not connect to server")
exit()
return sock, receiver, client
def recvDaemon(socket):
"""
A receiver thread that handles asynchronous messaging from the server
"""
while True:
e.clear()
data = socket.recv(4096)
if not data:
return
responseDict = json.loads(data.decode("utf-8"))
response = responseDict.get("response")
command = responseDict.get("command")
if not response:
if command == "list":
print("There are no rooms on the server")
else:
print("Error: received empty response from server")
e.set()
printPrompt()
continue
elif response == "ping":
continue
else:
now = datetime.datetime.now()
print(
"\n[{}:{}:{}] - {}".format(now.hour, now.minute, now.second, str(response).rstrip())
)
e.set()
printPrompt()
def clientProcess(receiver):
"""
The client process provides a command line interface for the user
"""
while True:
if not receiver.is_alive():
return
argv = sys.stdin.readline()
argv = argv.split()
args = parser.parseCommand(argv)
if args:
jsonString = buildPacket(vars(args))
if not jsonString:
print("Error: no username set. Please run 'user' command first")
printPrompt()
continue
sock.sendall(jsonString.encode("utf-8"))
if args.command == "quit":
return
try:
e.wait(5)
except:
print("Error: response from server timed out")
return
else:
printPrompt()
continue
def printPrompt():
sys.stdout.write("\n> ")
sys.stdout.flush()
sock, recvDaemon, client = establishConn()
printPrompt()
while True:
if not recvDaemon.is_alive():
if not client.is_alive():
sys.exit()
print("Error: connection to server was lost")
sys.exit()