python的tkinter、socket庫開發(fā)tcp的客戶端和服務端詳解
一、tcp通訊流程和開發(fā)步驟
1、tcp客戶端和服務端通訊流程圖
套接字是通訊的利器,連接時要經(jīng)過三次握手建立連接,斷開連接要經(jīng)過四次揮手斷開連接。
2、客戶端開發(fā)流程
- 1)創(chuàng)建客戶端套接字
- 2)和服務端器端套接字建立連接
- 3)發(fā)送數(shù)據(jù)
- 4)接收數(shù)據(jù)
- 5)關閉客戶端套接字
3、服務端開發(fā)流程
- 1)創(chuàng)建服務端套接字
- 2)綁定ip和端口號
- 3)設置監(jiān)聽
- 4)等待客戶端連接
- 5)接收數(shù)據(jù)
- 6)發(fā)送數(shù)據(jù)
- 7)關閉套接字
二、客戶端的實現(xiàn)
使用python的tkinter庫實現(xiàn)圖形化界面,使用類來實現(xiàn)tcp的客戶端和服務端
1、構造方法__init__初始化圖形界面
設置了三個按鈕
- 1)連接服務器的按鈕: 用來發(fā)送請求連接服務端。
- 2)斷開連接按鈕:用來關閉連接。
- 3)發(fā)送消息按鈕:來向服務端發(fā)送消息。
2、連接服務器的函數(shù)
- 1) tk.messagebox.showinfo: 彈窗,用來提示用戶。
- 2)socket.socket(socket.AF_INET, socket.SOCK_STREAM): 創(chuàng)建套接字。
參數(shù)1:ipv4協(xié)議,參數(shù)2:表示tcp協(xié)議
- 3)tcp_client_socket.connect(): 連接服務端,參數(shù)必須是一個元組。
3、發(fā)送消息函數(shù)
- 1)send_entry.get(): 獲取輸入框的內容。
- 2)encode():編碼。
- 3)tcp_client_socket.send(): 發(fā)送數(shù)據(jù)。
- 4)Thread(): 創(chuàng)建線程,防止阻塞。
參數(shù)1:target=要執(zhí)行的函數(shù),參數(shù)2:守護主線程。
- 5) .start(): 開啟線程。
4、接收消息函數(shù)
- recv_data = tcp_client_socket.recv(1024).decode('utf-8'): 接收消息并解碼。
5、斷開連接函數(shù)
- tcp_client_socket.close(): 關閉客戶端套接字。
三、服務端的實現(xiàn)
1、構造方法__init__初始化圖形界面
設置了四個按鈕:
- 1)啟動服務端按鈕:用來初始化服務端。
- 2)接收連接按鈕:接收客戶端請求的連接。
- 3)接收消息按鈕:接收客戶端發(fā)來的消息,需要手動接收。
- 4)發(fā)送消息按鈕:向客戶端發(fā)送消息。
2、啟動服務端函數(shù)
- 1)tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM):創(chuàng)建服務器端套接字對象。
- 2)tcp_server_socket.bind(("", 8888)): 綁定IP地址與端口號,端口可以自行設置,但客戶端必須和服務端保持一致。
- 3)tcp_server_socket.listen(5):監(jiān)聽連接,5表示最大連接數(shù)。
3、接收連接函數(shù)
- conn_socket, ip_port = tcp_server_socket.accept():等待接收客戶端連接請求。
4、發(fā)送消息函數(shù)
- conn_socket.send(): 發(fā)送數(shù)據(jù)
5、接收消息函數(shù)
- conn_socket.recv(1024).decode():接收數(shù)據(jù)并解碼
- conn_socket.close(): 關閉連接
- tcp_server_socket.close():關閉套接字
四、效果圖
使用說明:
- 1、先啟動服務端,在啟動客戶端,再服務端點擊接收連接按鈕接收客戶端發(fā)來的連接請求
- 2、客戶端輸入消息,點擊發(fā)送消息
- 3、服務端點擊接收消息,就會在下發(fā)文本框顯示消息
- 4、服務端回消息,客戶端會自動接收消息并顯示在下方的文本框
五、代碼
1、客戶端
import socket import tkinter as tk import tkinter.messagebox from threading import Thread # 創(chuàng)建tcp客戶端 class TcpClientSocket: def __init__(self): self.tcp_client_socket = None self.root = tk.Tk() self.root.title('tcp客戶端') self.root.geometry('500x350') # 連接 self.con_btn = tk.Button(self.root, text="連接服務端", width=10, command=self.connect) self.con_btn.place(x=100, y=20) # 斷開連接 self.discon_btn = tk.Button(self.root, text="斷開連接", width=10, command=self.disconnect) self.discon_btn.place(x=300, y=20) # 文本輸入框 self.send_entry = tk.Entry(self.root, width=50) self.send_entry.place(x=50, y=80) # 發(fā)送消息按鈕 self.send_btn = tk.Button(self.root, text="發(fā)送消息", command=self.send) self.send_btn.place(x=420, y=75) # 消息框 self.msg_test = tk.Text(self.root, width=70, height=16) self.msg_test.place(x=2, y=125) self.root.mainloop() # 連接服務端 def connect(self): try: if self.tcp_client_socket: tk.messagebox.showinfo('提示', '已是連接狀態(tài)') # 每次連接服務端就將上一次的記錄清除 self.msg_test.delete(1.0, tk.END) self.send_entry.delete(0, tk.END) # 創(chuàng)建客戶端socket self.tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 連接,端口可以改變 self.tcp_client_socket.connect(('127.0.0.1', 8888)) self.msg_test.insert(tk.END, "連接到服務端, 請輸入信息...\n") except Exception as e: self.msg_test.insert(tk.END, f"連接失敗的原因是: {e}") # 發(fā)送消息 def send(self): # 從輸入框獲取數(shù)據(jù) input_data = self.send_entry.get() self.tcp_client_socket.send(input_data.encode(encoding='utf-8')) self.msg_test.insert(tk.END, f"客戶端:{str(input_data)}\n") # 使用線程,防止未響應 receive_thread = Thread(target=self.receive, daemon=True) receive_thread.start() def receive(self): if self.tcp_client_socket: rec_msg = self.tcp_client_socket.recv(1024).decode(encoding='utf-8') self.msg_test.insert(tk.END, f"服務端:{str(rec_msg)}\n") # 斷開連接 def disconnect(self): if self.tcp_client_socket: self.send_entry.delete(0, tk.END) self.msg_test.insert(tk.END, "斷開連接") self.tcp_client_socket.send('#'.encode(encoding='utf-8')) # 發(fā)送'#‘斷開連接 self.tcp_client_socket.close() # 關閉客戶端 else: tk.messagebox.showinfo('提示', '未連接到服務端') if __name__ == '__main__': TcpClientSocket()
2、服務端
import socket import tkinter as tk from threading import Thread import tkinter.messagebox class TcpServerSocket: def __init__(self): self.conn_socket = None self.tcp_server_socket = None self.root = tk.Tk() self.root.title('tcp服務端') self.root.geometry('500x350') # 連接 self.con_btn = tk.Button(self.root, text="啟動服務端", width=10, command=self.start_server) self.con_btn.place(x=100, y=20) # 接收消息 self.status_btn = tk.Button(self.root, text="接收連接", width=10, command=self.status) self.status_btn.place(x=200, y=20) # 接收消息 self.rev_btn = tk.Button(self.root, text="接收消息", command=self.receive) self.rev_btn.place(x=300, y=20) # 文本輸入框 self.send_entry = tk.Entry(self.root, width=50) self.send_entry.place(x=50, y=80) # 發(fā)送消息按鈕 self.send_btn = tk.Button(self.root, text="發(fā)送消息", command=self.send) self.send_btn.place(x=420, y=75) # 消息框 self.msg_test = tk.Text(self.root, width=70, height=16) self.msg_test.place(x=2, y=125) self.root.mainloop() # 啟動tcp服務端 def start_server(self): try: # 每次連接服務端就將上一次的記錄清除 self.send_entry.delete(0, tk.END) self.msg_test.delete(1.0, tk.END) # 創(chuàng)建服務端socket self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.tcp_server_socket.bind(('', 8888)) # 綁定 self.tcp_server_socket.listen(5) # 監(jiān)聽的最大連接數(shù) self.msg_test.insert(tk.END, f"服務端啟動成功!\n") except Exception as e: self.msg_test.insert(tk.END, f"啟動失敗的原因是: {e}") def status(self): if self.conn_socket is None: self.conn_socket, ip_port = self.tcp_server_socket.accept() elif self.conn_socket: self.msg_test.insert(tk.END, "客戶端已連接\n") else: tk.messagebox.showinfo('提示', "客戶端未連接") def send(self): try: input_data = self.send_entry.get() self.conn_socket.send(input_data.encode(encoding='utf-8')) self.msg_test.insert(tk.END, f"服務端:{str(input_data)}\n") except Exception as e: self.msg_test.insert(tk.END, f"發(fā)送失敗的原因: {e}") def receive(self): rec_msg = self.conn_socket.recv(1024).decode(encoding='utf-8') print(rec_msg) # 獲取到#斷開連接 if rec_msg == '#': self.conn_socket.close() self.tcp_server_socket.close() self.msg_test.insert(tk.END, f"客戶端斷開連接\n") return self.msg_test.insert(tk.END, f"客戶端:{str(rec_msg)}\n") if __name__ == '__main__': TcpServerSocket()
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Python使用matplotlib.pyplot?as?plt繪圖圖層優(yōu)先級問題
這篇文章主要介紹了Python使用matplotlib.pyplot?as?plt繪圖圖層優(yōu)先級問題.文章圍繞主題展開詳細內容需要的小伙伴可以參考一下2022-04-04Python: tkinter窗口屏幕居中,設置窗口最大,最小尺寸實例
這篇文章主要介紹了Python: tkinter窗口屏幕居中,設置窗口最大,最小尺寸實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03TensorFlow入門使用 tf.train.Saver()保存模型
這篇文章主要介紹了TensorFlow入門使用 tf.train.Saver()保存模型,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-04-04python-docx修改已存在的Word文檔的表格的字體格式方法
今天小編就為大家分享一篇python-docx修改已存在的Word文檔的表格的字體格式方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-05-05