import json import socket import struct import sys import threading from datetime import datetime PORT = 1234 HEADER_LENGTH = 2 def receive_fixed_length_msg(sock, msglen): message = b'' while len(message) < msglen: chunk = sock.recv(msglen - len(message)) # preberi nekaj bajtov if chunk == b'': raise RuntimeError("socket connection broken") message = message + chunk # pripni prebrane bajte sporocilu return message def receive_json(sock): # preberi glavo sporocila (v prvih 2 bytih je dolzina sporocila) header = receive_fixed_length_msg(sock, HEADER_LENGTH) message_length = struct.unpack("!H", header)[0] # pretvori dolzino sporocila v int message = None if message_length > 0: # ce je vse OK message = receive_fixed_length_msg(sock, message_length) # preberi sporocilo message = message.decode("utf-8") message = json.loads(message) return message def send_json(sock, data): data["time"] = datetime.now().strftime("%c") # pretvori sporocilo v niz bajtov, uporabi UTF-8 kodno tabelo encoded_data = json.dumps(data).encode("utf-8") # ustvari glavo v prvih 2 bytih je dolzina sporocila (HEADER_LENGTH) # metoda pack "!H" : !=network byte order, H=unsigned short header = struct.pack("!H", len(encoded_data)) data = header + encoded_data # najprj posljemo dolzino sporocilo, sele nato sporocilo samo sock.sendall(data) def send_username(sock, username): send_json(sock, { "type": "username", "data": username, }) def send_message(sock, message): send_json(sock, { "type": "message", "data": message, }) # message_receiver funkcija tece v loceni niti def message_receiver(): while True: msg_received = receive_json(sock) msg_type = msg_received["type"] data = msg_received["data"] time = msg_received["time"] match msg_type: case "message": username = msg_received["username"] print(f'[{time}] [{username}] : {data}') case "error": print(f'Error: {data}') # povezi se na streznik print("[system] connecting to chat server ...") sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(("localhost", PORT)) print("[system] connected!") # zazeni message_receiver funkcijo v loceni niti thread = threading.Thread(target=message_receiver) thread.daemon = True thread.start() username = input("enter username: ") send_username(sock, username) # pocakaj da uporabnik nekaj natipka in poslji na streznik while True: try: msg_send = input("") send_message(sock, msg_send) except KeyboardInterrupt: sys.exit()