Base Client
Chat client handling message emission and reception
Parameters
| Name |
Type |
Description |
Default |
server_host |
str |
ip address of remote server |
'localhost' |
server_port |
int |
port of remote server |
1234 |
Example
client = Client(
server_host="localhost",
server_port=1234,
)
client.run()
close(self)
Show source code in base/client.py
| def close(self) -> None:
"""Close sever connection and interrupt client."""
logger.info("Close client writer")
if self.writer:
self.writer.close()
|
Close sever connection and interrupt client.
on_new_message(self, data)
Show source code in base/client.py
76
77
78
79
80
81
82
83
84 | async def on_new_message(self, data: Dict[str, Any]) -> None:
"""
Handle a new message received by server.
This method simply prints it with a `<<<` prefix.
Arguments:
data: dictionary containing `from` (=sender id) and `message` keys
"""
print(f"<<< {data['from']} > {data['message']}")
|
Handle a new message received by server.
This method simply prints it with a <<< prefix.
Parameters
| Name |
Type |
Description |
Default |
data |
Dict[str, Any] |
dictionary containing from (=sender id) and message keys |
required |
receive_messages(self)
Show source code in base/client.py
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 | async def receive_messages(self) -> None:
"""
Listen messages one by one received from server.
!!! note
after decoding, messages received are json with the following format:
```json
{
"from": str, // sender id
"message": str, // message
}
```
For each message, this method decodes the received json and "fire and forget"
a task with `self.on_new_message()` method.
"""
while True:
if not self.reader:
raise ConnectionAbortedError("No socket reader")
# message received one by one because server add \n after every message
data = await self.reader.readline()
if not data:
logger.warning("Empty message received from server")
raise ConnectionAbortedError("Empty message received from server")
logger.debug("Message received from server %s" % data.decode())
asyncio.ensure_future(self.on_new_message(data=json.loads(data.decode())))
|
Listen messages one by one received from server.
Note
after decoding, messages received are json with the following format:
{
"from": str, // sender id
"message": str, // message
}
For each message, this method decodes the received json and "fire and forget"
a task with self.on_new_message() method.
run(self)
Show source code in base/client.py
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155 | def run(self) -> None:
"""
Run client by starting an event loop that listen to user input and
server messages.
"""
try:
self.loop.run_until_complete(self.start())
self.loop.create_task(self.wait_for_message())
self.loop.create_task(self.receive_messages())
self.loop.run_forever()
except KeyboardInterrupt:
logger.warning("Client closed manually by user")
# exceptions raised by tasks are handled in handle_exception
except Exception as e:
logger.error("Uncatched exception %s" % e)
finally:
logger.info("Close client")
self.close()
logger.debug("Close loop")
self.loop.close()
|
Run client by starting an event loop that listen to user input and
server messages.
send_message(self, message)
Show source code in base/client.py
48
49
50
51
52
53
54
55
56
57
58
59 | def send_message(self, message: str) -> None:
"""
Send message to server
Arguments:
message: to send to server
"""
if not self.writer:
raise ConnectionAbortedError("Client has no active writer")
self.writer.write(message.encode("utf8"))
|
Send message to server
Parameters
| Name |
Type |
Description |
Default |
message |
str |
to send to server |
required |
start(self)
Show source code in base/client.py
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133 | async def start(self) -> None:
"""
Start server connection
Raise:
ConnectionRefusedError: if connection to server failed
"""
logger.debug("Register the open socket to wait for data")
try:
self.reader, self.writer = await asyncio.open_connection(
host=self.server_host, port=self.server_port,
)
except OSError:
raise ConnectionRefusedError("Impossible to find server")
|
Start server connection
Exceptions
| Type |
Description |
ConnectionRefusedError |
if connection to server failed |
wait_for_message(self)
Show source code in base/client.py
61
62
63
64
65
66
67
68
69
70
71
72
73
74 | async def wait_for_message(self) -> None:
"""
Listen for user input and send input to server.
"""
logger.debug("wait for user input")
while True:
message = await ainput(">>>")
if message:
if message == ":q":
self.send_message(message)
break
else:
logger.debug("send %s to server" % message)
self.send_message(message)
|
Listen for user input and send input to server.