首頁>技術>

利用tkinter,Thread,socket編寫聊天工具介面版本

client:

新支援功能:

1,登出賬號。

2,新增新使用者(固定)。

3,使用者資訊顯示。

4,賬號退出。

5,介面劃分。

6,朋友賬號顯示。

8,Menu button的顯示。

上版本支援功能:

1,web登入。

2,賬號認證

3,賬號註冊

4,資訊傳送。

5,資訊顯示

server:

新增加功能:

1,賬號新朋友新增功能。

2,賬號老朋友記錄。

4,新增朋友時判斷。

上版本支援功能:

1,web啟動server。

2,登入資訊顯示。

3,賬號儲存。

4,賬號認證。

Server程式碼:

import tkinter as tkimport socket, threadingimport picklefrom collections import defaultdictimport oswindow = tk.Tk()  # 建立主視窗window.title('Fiona Server')window.geometry("400x400+200+20")users = {}  # 使用者字典,也可以連線資料庫def run(ck, ca):    userName = ck.recv(1024).decode()  # 接受客戶端傳送的資訊以1k作為單位這裡接受到的資訊為byte型別    users[userName.split("登入")[0]] = ck  # 解碼並儲存使用者的資訊    with open("usrs_info.pickle", "rb") as usr_file:        exist_usrs_info = pickle.load(usr_file)    if "登入" in userName:        account = userName.split("登入")        exist_usrs_info = defaultdict(str, exist_usrs_info)        if exist_usrs_info[account[0]] == account[1]:            ck.sendall("登入成功,可以嗨了\n".encode())            info = account[0] + "登入成功\n"            users[userName.split("登入")[0]] = ck            print(users)        elif exist_usrs_info[account[0]] != account[1]:            ck.sendall("密碼認證失敗\n".encode())            ck.close()            info = account[0] + "認證失敗\n"        else:            ck.sendall("沒有你的賬號,請先註冊\n".encode())            ck.close()    elif "註冊" in userName:        account = userName.split("註冊")        exist_usrs_info[account[0]] = account[1]        with open("usrs_info.pickle", "wb") as usr_file:            pickle.dump(exist_usrs_info, usr_file)        ck.sendall("註冊成功,請重新登入\n".encode())        print("open1")        f = open("{user}_friend_info.txt".format(user=account[0]),"ab+")        f.write(("Old Friend List :\n;").encode())        f.close()        ck.close()        info = account[0] + "註冊成功\n"        print(users)    elif not userName:        ck.close()        print(users)    text.insert(tk.INSERT, info)    while True:        rData = ck.recv(1024)  # 接受客戶端傳送的資訊以1k作為單位這裡接受到的資訊為byte型別        dataStr = rData.decode("utf-8")        if "del" in dataStr:            account = dataStr.split("del")            if exist_usrs_info[account[0]] == account[1]:                del exist_usrs_info[account[0]]                with open("usrs_info.pickle", "wb") as usr_file:                    pickle.dump(exist_usrs_info, usr_file)                if os.path.exists("{user}_friend_info.txt".format(user=account[0])):                    print("The file exist")                    os.remove("{user}_friend_info.txt".format(user=account[0]))                else:                    print("The file does not exist")                ck.close()            else:                break        elif "getoldfriend" in dataStr:            account = dataStr.split("getoldfriend")            print(account[0])            print("open1")            with open("{user}_friend_info.txt".format(user=account[0]), "r") as usr_file:                your_friend_info = usr_file.read()                print(your_friend_info)            ck.sendall(your_friend_info.encode())        elif "addfriend" in dataStr:            account = dataStr.split("addfriend")            f = open("{user}_friend_info.txt".format(user=account[0]), "rb+")            data = f.read().decode()            if ";"+account[1]+";" in data:                ck.sendall("朋友{account}已經存在,不需要新增!\n".format(account=account[1]).encode())            else:                with open("usrs_info.pickle", "rb") as usr_file:                    exist_usrs_info = pickle.load(usr_file)                if account[1] in exist_usrs_info:                    f.write(("{account};".format(account=account[1])).encode())                    ck.sendall("朋友: {account} 已新增!\n".format(account=account[1]).encode())                else:                    ck.sendall("朋友: {account}不存在!\n".format(account=account[1]).encode())            f.close()        else:            infolist = dataStr.split(":")  # 分割字串從而得到所要傳送的使用者名稱和客戶端所傳送的資訊            users[infolist[0]].send((userName + ":" + infolist[1] + "\n").encode("utf-8"))        # 要傳送資訊的客戶端向目標客戶端傳送資訊def start():    ipStr = eip.get()  # 從輸入端中獲取ip    portStr = eport.get()  # 從輸入端中獲取埠,注意埠取得時候不能被佔用(可以取8080,9876,等)    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # socked所準守ipv4或ipv6,和相關協議的    server.bind((ipStr, int(portStr)))  # 繫結ip和埠號!!!1:注意輸入的埠號是str型而這裡的要傳入int型    server.listen(10)  # 設定監聽,和設定連線的最大的數量    printStr = "伺服器啟動成功\n"  # ,是否連線成功    text.insert(tk.INSERT, printStr)  # 顯示在資訊視窗中    while True:  # 這裡用死迴圈是因為模擬的伺服器要一直執行        ck, ca = server.accept()  # 接受所連線的客戶端的資訊        t = threading.Thread(target=run, args=(ck, ca))  # 每連線一個客戶端就開啟一個執行緒        t.start()  # 開啟執行緒def startSever():    s = threading.Thread(target=start)  # 啟用一個執行緒開啟伺服器    s.start()  # 開啟執行緒# 下面是關於介面的操作labelIp = tk.Label(window, text='Server IP').grid(row=0, column=0)labelPort = tk.Label(window, text='Connect port').grid(row=1, column=0)eip = tk.Variable()eport = tk.Variable()eip.set("192.168.68.202")eport.set(8001)entryIp = tk.Entry(window, textvariable=eip).grid(row=0, column=1)entryPort = tk.Entry(window, textvariable=eport).grid(row=1, column=1)button = tk.Button(window, text="啟動", command=startSever).grid(row=2, column=0)text = tk.Text(window, height=5, width=30)labeltext = tk.Label(window, text='連線訊息').grid(row=3, column=0)text.grid(row=200, column=1)window.mainloop()

7
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • python內建資料結構和字串