打算為基於廣播的UDP聊天室做一個UI介面,並且可以隨時切換埠來做到切換頻道的效果,但在接收封包的部分遇到了問題。
VScode報錯:
in recv
recv_socket.bind(('', port))
OSError: [WinError 10022] 提供了一個不正確的引數。
程式碼:
import tkinter as tk
from socket import socket, AF_INET, SOCK_DGRAM, SOL_SOCKET, SO_REUSEADDR, SO_BROADCAST
from time import sleep
from threading import Thread
#發送封包
def send(event=None):
entry = send_entry.get()
send_entry.delete(0, "end")
port = int(channel_entry.get())
sendSocket = socket(AF_INET, SOCK_DGRAM)
sendSocket.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
sendSocket.sendto(entry.encode("utf-8"), ('255.255.255.255', port))
#接收器
recv_socket = socket(AF_INET, SOCK_DGRAM)
recv_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
recv_socket.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
def recv():
text_box.config(state=tk.NORMAL)
text_box.insert(tk.END, "[*] 載入 UDP 訊息接收器完成\n")
text_box.config(state=tk.DISABLED)
while True:
port = int(channel_entry.get())
recv_socket.bind(('', port))
try:
recv_data = recv_socket.recvfrom(1024)
text_box.config(state=tk.NORMAL)
text_box.insert(tk.END, f"{recv_data[1][0]}:{recv_data[0].decode('utf-8')}\n")
text_box.config(state=tk.DISABLED)
text_box.see(tk.END)
sleep(1)
except OSError:
text_box.config(state=tk.NORMAL)
text_box.insert(tk.END, "[*] 超過單次字數限制\n")
text_box.config(state=tk.DISABLED)
text_box.see(tk.END)
#接收器線呈
Thread(target=recv, daemon=True).start()
app.mainloop()
那個錯誤是說你重複 bind 了這個 socket。bind()
只需要做一次,不該放在 while
內:
#接收器
recv_socket = socket(AF_INET, SOCK_DGRAM)
recv_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
recv_socket.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
recv_socket.bind(('', port))
def recv():
text_box.config(state=tk.NORMAL)
text_box.insert(tk.END, "[*] 載入 UDP 訊息接收器完成\n")
text_box.config(state=tk.DISABLED)
while True:
port = int(channel_entry.get())
try:
.
.
.
謝謝你,原本我也這樣寫,是後來我將它移進去的。但是我想做到切換的功能,在recvfrom
之前不是得先bind
嗎?目前打算使用Tkinter的after
來callback線呈,而recv
的壽命改成有限的。但不知為何一直沒有效果QQ
不太懂你要的功能,我對 Tkinter 也不熟。但我猜你要的方式可以透過依賴注入的方式達成,或是把 socket 當作全域變數來傳入,這兩種都是在 function 外面就建好 socket。
總之只能 bind 一次,要不就重建一個 socket,只是這樣開銷有點高。