Advertisement
noctual

Chat Client

Apr 11th, 2021
298
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.86 KB | None | 0 0
  1. import threading, socket, json, os
  2. from tkinter import *
  3. from tkinter import filedialog as fd
  4. from datetime import datetime
  5.  
  6. SERVER_ADDR = '127.0.0.1', 1111  # Данные сервера
  7.  
  8. class ChatClientWindow(Tk):
  9.     def __init__(self, server_adr):
  10.         super().__init__()
  11.         self.server_adr = server_adr
  12.         self._chat_sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  13.         self._chat_sock.connect(self.server_adr)
  14.         self._initUI()
  15.         rcv = threading.Thread(target=self._loop_recv)
  16.         rcv.start()
  17.         self.mainloop()
  18.    
  19.     def _initUI(self):
  20.         self.title("Чат")
  21.         self.geometry('600x400+200+100')
  22.  
  23.         # Name
  24.         f_header = Frame(self)
  25.  
  26.         self.setName = Button(f_header, text="Установить имя", command=self._setNickname)
  27.         self.setName.pack(side=RIGHT)
  28.  
  29.         self.nameStrVar = StringVar(value="")
  30.         self.nameEntry = Entry(f_header, textvariable=self.nameStrVar, bd=0)
  31.         self.nameEntry.pack(side=RIGHT, fill=BOTH, expand=True)
  32.  
  33.         f_header.pack(fill=X)
  34.  
  35.         # Messanges
  36.         self.messText = Text(width=25, height=5, bg="darkgreen", fg='white', wrap=WORD)
  37.         self.messText.pack(fill=BOTH, expand=True)
  38.  
  39.         # essage input field
  40.         f_footer = Frame(self)
  41.        
  42.         self.sendFileButton = Button(f_footer, text="Отправить файл", command=self._sendFile)
  43.         self.sendFileButton.pack(side=RIGHT)
  44.  
  45.         self.sendButton = Button(f_footer, text="Отправить", command=self._sendMess)
  46.         self.sendButton.pack(side=RIGHT)
  47.  
  48.         self.messStrVar = StringVar(value="")
  49.         self.messEntry = Entry(f_footer, textvariable=self.messStrVar, bd=0)
  50.         self.messEntry.pack(side=RIGHT, fill=BOTH, expand=True)
  51.  
  52.         f_footer.pack(fill=X)
  53.  
  54.     def _setNickname(self):
  55.         nickname = self.nameStrVar.get()
  56.         if len(nickname) > 0 and len(nickname) < 32:
  57.             self.nickname = nickname
  58.             bmess = nickname.encode('utf-8')
  59.             self._chat_sock.sendto(f'NICKNAME\r\nContent-Length:{len(bmess)}\r\n\r\n'.encode('utf-8') + bmess, self.server_adr)
  60.  
  61.     def _sendMess(self):
  62.         messange = self.messStrVar.get()
  63.         if len(messange) > 0:
  64.             bmess = messange.encode('utf-8')
  65.             self._chat_sock.send(f'MESSANGE\r\nContent-Length:{len(bmess)}\r\n\r\n'.encode('utf-8') + bmess)
  66.             self.messStrVar.set("")
  67.  
  68.     def _sendFile(self):
  69.         pathfile = fd.askopenfilename()
  70.         with open(pathfile, 'rb') as f:
  71.             filelen = os.fstat(f.fileno()).st_size
  72.             filename = os.path.basename(pathfile)
  73.             self._chat_sock.send(f'FILE\r\nContent-Length:{filelen}\nFile-name:{filename}\r\n\r\n'.encode('utf-8'))
  74.             self._chat_sock.sendfile(f)
  75.  
  76.     def _loop_recv(self):
  77.         request = b''
  78.         while True:
  79.             try:
  80.                 indexEndHead = request.find(b'\r\n\r\n')
  81.                 if indexEndHead != -1:            
  82.                     head = request[:indexEndHead].splitlines()
  83.                     heads = {title[0]: title[1] for title in [line.split(b':', 1) for line in head[1:]]}
  84.                     if len(request[indexEndHead+4:]) >= int(heads[b'Content-Length']):
  85.                         data, request = request[indexEndHead+4:indexEndHead+4+int(heads[b'Content-Length'])], request[indexEndHead+4+int(heads[b'Content-Length']):]
  86.                         messjson = json.loads(data.decode('utf-8'))
  87.                         if messjson['type'] == 'mess':
  88.                             mess = f"[{datetime.fromtimestamp(messjson['date'])}] {messjson['name']}: {messjson['text']}\n"
  89.                             self.messText.insert(END, mess)
  90.                         elif messjson['type'] == 'system':
  91.                             mess = f"[{datetime.fromtimestamp(messjson['date'])}] {messjson['text']}\n"
  92.                             self.messText.insert(END, mess)
  93.                         elif messjson['type'] == 'file':
  94.                             with open(messjson['filename'], 'wb') as f:
  95.                                 numBytes = 0
  96.                                 while numBytes < int(messjson['len']):
  97.                                     data = self._chat_sock.recv(1024)
  98.                                     numBytes += len(data)
  99.                                     f.write(data)
  100.                             mess = f"[{datetime.fromtimestamp(messjson['date'])}] received file {messjson['filename']} from {messjson['name']}\n"
  101.                             self.messText.insert(END, mess)
  102.                         self.messText.see(END)
  103.                 else:
  104.                     request += self._chat_sock.recv(1024)
  105.             except:
  106.                 self._chat_sock.close()
  107.                 break
  108.  
  109. def main():
  110.     ChatClientWindow(SERVER_ADDR)
  111.  
  112. if __name__ == '__main__':
  113.     main()
  114.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement