-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathClientChat.py
More file actions
150 lines (123 loc) · 5.3 KB
/
ClientChat.py
File metadata and controls
150 lines (123 loc) · 5.3 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
from threading import Thread
from Console import Console
from typing import Union
import threading
import socket
import time
import sys
BUFFER_SIZE: int = 1024
QUIT: str = '/quit'
class ClientTCP():
'''
Represents a TCP client for the chat application.
Handles connection to the server, sending and receiving messages.
'''
def __init__(self, host: str, port: int, username: str):
'''
Initializes the ClientTCP instance.
Args:
host (str): The server's hostname or IP address.
port (int): The server's port number.
username (str): The username for the client.
'''
self.host: str = host
self.port: int = port
self.username: str = username
self.clientSocket: Union[None, socket.socket] = None
self.disconnected: bool = True
self.stopEvent: Union[None, threading.Event] = None
self.console: Console = Console()
def __sendMessage__(self, message: str):
'''
Sends a message to the connected server.
Args:
message (str): The message string to send.
'''
try: self.clientSocket.sendall(message.encode('utf-8'))
except Exception as e:
self.console.printlnError('Cound\'t send message. Make sure client is connected properly!')
self.disconnect()
def disconnect(self):
'''
Disconnects the client from the server.
Closes the socket and sets the stop event for threads.
'''
self.console.printlnGreen('Disconnecting from server...')
self.clientSocket.close()
self.stopEvent.set()
self.disconnected = True
self.console.printlnGreen('Disconnected.')
def connect(self):
'''
Establishes a connection to the server and starts communication.
It creates a socket, connects, starts a message sender thread,
sends the username, and then enters a loop to receive messages.
'''
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as clientSocket:
try:
self.clientSocket = clientSocket
self.clientSocket.connect((self.host, self.port))
self.disconnected = False
self.stopEvent: threading.Event = threading.Event()
messageSenderThread: Thread = Thread(target=self.__runMessageSender__, name='messageSender', args=(self.stopEvent,))
messageSenderThread.start()
self.__sendMessage__(self.username)
while True:
data: bytes = self.clientSocket.recv(BUFFER_SIZE)
currentText: str = self.console.getBackTextToString('[Send Message] ->', 3, '{Timeout ERROR, current message erased.} -> ')[1:]
self.console.clearLine()
self.console.moveFront()
message: str = data.decode('utf-8').split()
if message[0] == 'blue': self.console.printlnBlue(' '.join(message[1:]))
elif message[0] == 'green': self.console.printlnGreen(' '.join(message[1:]))
else: self.console.println(' '.join(message))
self.console.printDim(f'[Send Message] -> ')
self.console.print(currentText)
except ConnectionRefusedError:
self.console.printlnError('Connection refused!')
except Exception as e:
self.console.println('')
self.console.printlnError('Issue connecting to server!')
if not self.disconnected: self.disconnect()
def __runMessageSender__(self, stopEvent):
'''
Runs in a separate thread to handle sending user input as messages.
Args:
stopEvent (threading.Event): Event used to signal the thread to stop.
'''
while not self.stopEvent.is_set():
self.console.printDim('[Send Message] -> ')
message: str = self.console.input()
linesCovered: int = self.console.getLinesCovered(f'[Send Message] -> {message}')
for i in range(linesCovered):
self.console.clearLine()
self.console.moveUp()
self.console.moveFront()
self.console.println(f'[{self.username}] -> {message}')
if self.disconnected: break
elif message.lower() == QUIT:
self.disconnect()
else: self.__sendMessage__(message)
if __name__ == '__main__':
host: str = ''
port: int = 0
username: str = ''
if not (len(sys.argv) == 1 or len(sys.argv) == 4):
print('Usage: python ClientChat.py [server address] [server port] [username]')
exit(0)
if len(sys.argv) == 1:
tempConsole: Console = Console()
tempConsole.printDim('Enter the server address: ')
host = tempConsole.input()
tempConsole.printDim('Enter the server port: ')
port = int(tempConsole.input())
tempConsole.printDim('Enter a username: ')
username = tempConsole.input()
tempConsole.close()
else:
host = sys.argv[1]
port = int(sys.argv[2])
username = sys.argv[3]
client: ClientTCP = ClientTCP(host, port, username)
client.connect()
time.sleep(2)