-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclient.py
More file actions
205 lines (176 loc) · 7.34 KB
/
client.py
File metadata and controls
205 lines (176 loc) · 7.34 KB
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
import socket
import json
from tabulate import tabulate
import threading
import ast
import select
class BaseThread(threading.Thread):
def __init__(self, callback=None, callback_args=None, *args, **kwargs):
target = kwargs.pop('target')
super(BaseThread, self).__init__(target=self.target_with_callback, *args, **kwargs)
self.callback = callback
self.method = target
self.callback_args = callback_args
def target_with_callback(self):
self.method()
if self.callback is not None:
if self.callback_args is not None:
self.callback(*self.callback_args)
else:
self.callback()
class Client:
def __init__(self, bufferSize=1024):
self.connected = False
self.listener = BaseThread(target=self.listen, callback=self.resetConnection)
self.serverAddressPort = None
self.bufferSize = bufferSize
self.UDPClientSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
def listen(self):
while True:
# Attempt to listen. Sometimes an error occurs even if already connected.
try:
bytesAddressPair = client.recieve()
# Convert recieved inputs
byteMsg = bytesAddressPair[0]
ServerMsgDict = ast.literal_eval(json.loads(byteMsg.decode()))
print(ServerMsgDict["message"])
if not self.connected:
print("[Client]: Disconnected from Server...")
break
except:
print("Recieve Error: Connection to the Message Board Server has failed! Please check IP Address and Port Number.")
break
def test_join(self):
try:
# If there is no response from the server in 2 seconds then the connection failed
ready = select.select([self.UDPClientSocket], [], [], 2)
if ready[0]:
bytesAddressPair = client.recieve()
# Convert recieved inputs
byteMsg = bytesAddressPair[0]
ServerMsgDict = ast.literal_eval(json.loads(byteMsg.decode()))
print(ServerMsgDict["message"])
# If join testing is successful, start listening continuously
self.listener.start()
if not self.connected:
print("[Client]: Disconnected from Server...")
else:
print("Recieve Error: Connection to the Message Board Server has failed! Please check IP Address and Port Number.")
self.resetConnection()
except:
print("Recieve Error: Connection to the Message Board Server has failed! Please check IP Address and Port Number.")
self.resetConnection()
def join(self, s):
if self.connected == False:
self.serverAddressPort = (s[1], s[2])
try:
# Send to server using created UDP socket
self.connected = True
self.send({"command":"join"}, self.serverAddressPort)
self.test_join()
except:
self.connected = False
print("Join Error: Connection to the Message Board Server has failed! Please check IP Address and Port Number.")
else:
print("Currently Connected. Please do /leave first.")
def resetConnection(self):
# A thread can only be run once so assign a new one
self.listener = BaseThread(target=self.listen, callback=self.resetConnection)
self.serverAddressPort = None
self.connected = False
def leave(self):
# if not currently connected print error
if self.connected:
self.send({"command":"leave"}, self.serverAddressPort)
self.connected = False
else:
print("Error: Disconnection failed. Please connect to a server first.")
def register(self, s):
if self.connected:
s[0] = s[0].replace('/', '')
command = s[0]
handle = s[1]
self.send({"command":command, "handle":handle}, self.serverAddressPort)
else:
print("Error: Not Connected to a server!")
def msgAll(self, s):
if self.connected:
s[0] = s[0].replace('/', '')
command = s[0]
message = ' '.join(word for word in s[1::])
self.send({"command":command, "message":message}, self.serverAddressPort)
else:
print("Error: Not Connected to a server!")
def msgOne(self, s):
if self.connected:
s[0] = s[0].replace('/', '')
command = s[0]
handle = s[1]
message = ' '.join(word for word in s[2::])
self.send({"command":command, "handle": handle, "message":message}, self.serverAddressPort)
else:
print("Error: Not Connected to a server!")
def question(self):
# Print all description of commands
commands = [
["/join <server_ip_add> <port>", "Connect to the server application"],
["/leave", "Disconnect to the server application"],
["/register <handle>", "Register a unique handle or alias"],
["/all <message>", "Send message to all"],
["/msg <handle> <message>", "Send direct message to a single handle"],
["/?", "Request command help to output all Input Syntax commands for references"]
]
header = ["Command", "Description"]
print(tabulate(commands, headers=header))
def send(self, msg:str, address:tuple):
bytesToSend = str.encode(json.dumps(str(msg)))
self.UDPClientSocket.sendto(bytesToSend, (str(address[0]), int(address[1])))
def recieve(self):
return self.UDPClientSocket.recvfrom(self.bufferSize)
#####################
client = Client()
def parseInput(input):
s = input.split()
if not(s == []):
if "/join" in s[0]:
if not len(s)==3:
print("Error: Command parameters do not match or is not allowed.")
else:
client.join(s)
elif "/leave" in s[0]:
if not len(s)==1:
print("Error: Command parameters do not match or is not allowed.")
else:
client.leave()
elif "/register" in s[0]:
if not len(s)==2:
print("Error: Command parameters do not match or is not allowed.")
else:
client.register(s)
elif "/all" in s[0]:
if len(s)<2:
print("Error: Command parameters do not match or is not allowed.")
else:
client.msgAll(s)
elif "/msg" in s[0]:
if len(s)<3:
print("Error: Command parameters do not match or is not allowed.")
else:
client.msgOne(s)
elif "/?" in s[0]:
if not len(s)==1:
print("Error: Command parameters do not match or is not allowed.")
else:
client.question()
else:
print("Error: Command not found")
else:
print("Error: Command not found")
def clientProgram():
while True:
parseInput(input())
def main():
print("Client Started...")
program = threading.Thread(target=clientProgram)
program.start()
main()