-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchat_client.py
125 lines (98 loc) · 3.44 KB
/
chat_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
122
123
124
import select
import socket
import sys
import signal
import argparse
import threading
import pickle
import struct
import ssl
def send(channel, *args):
buffer = pickle.dumps(args)
value = socket.htonl(len(buffer))
size = struct.pack("L", value)
channel.send(size)
channel.send(buffer)
def receive(channel):
size = struct.calcsize("L")
size = channel.recv(size)
try:
size = socket.ntohl(struct.unpack("L", size)[0])
except struct.error as e:
return ''
buf = ""
while len(buf) < size:
buf = channel.recv(size - len(buf))
return pickle.loads(buf)[0]
SERVER_HOST = 'localhost'
stop_thread = False
def get_and_send(client):
while not stop_thread:
# Display 'me: ' before typing the message
sys.stdout.write('me:')
sys.stdout.flush()
data = sys.stdin.readline().strip()
if data:
send(client.sock, data)
class ChatClient():
def __init__(self, name, port, host=SERVER_HOST):
self.name = name
self.connected = False
self.host = host
self.port = port
self.context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
self.context.set_ciphers('AES128-SHA')
# Connect to server at port
try:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock = self.context.wrap_socket(
self.sock, server_hostname=host)
self.sock.connect((host, self.port))
print(f'Now connected to chat server@ port {self.port}')
self.connected = True
# Send my name
send(self.sock, 'NAME: ' + self.name)
data = receive(self.sock)
threading.Thread(target=get_and_send, args=(self,)).start()
except socket.error as e:
print(f'Failed to connect to chat server @ port {self.port}')
sys.exit(1)
def cleanup(self):
"""Close the connection and wait for the thread to terminate."""
self.sock.close()
def run(self):
""" Chat client main loop """
while self.connected:
try:
sys.stdout.flush()
# Wait for input from stdin and socket
# readable, writeable, exceptional = select.select([0, self.sock], [], [])
readable, writeable, exceptional = select.select(
[self.sock], [], [])
for sock in readable:
if sock == self.sock:
data = receive(self.sock)
if not data:
print('Client shutting down.')
self.connected = False
break
else:
sys.stdout.write('\r')
sys.stdout.write(data + '\n')
sys.stdout.write('me: ')
sys.stdout.flush()
except KeyboardInterrupt:
print(" Client interrupted. " "")
stop_thread = True
self.cleanup()
break
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('--port', action="store",
dest="port", type=int, required=True)
given_args = parser.parse_args()
port = given_args.port
print("Login")
name = input("Username: ")
client = ChatClient(name=name, port=port)
client.run()