我有一个侦听传入连接的套接字,一旦建立并且数据移动,我就可以使用按钮关闭连接,但是我可以使用按钮来停止连接甚至在建立连接和while循环开始之前套接字?
以下是套接字的代码:
def serverstart(self):
self.buttonswitch("1")
host = self.intip
port = 5000
s= socket.socket(socket.AF_INET6)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(1)
c, addr = s.accept()
print "Connection from: " + str(addr)
self.serverstatus = "1"
status = self.serverstatus
while status == "1":
data = c.recv(1500)
print len(data)
if not data:
break
data = str(data).upper()
c.send(data)
status = self.serverstatus
c.close()
s.close()
print "Closing socket"
self.buttonswitch("0")
我使用buttonswitch功能来启用和禁用停止和启动按钮以及服务器的状态
编辑:我摆脱了self.serverstatus变量并添加了它(创建一个连接到套接字只是为了关闭它):
def serverstop(self, status):
s = socket.socket(socket.AF_INET6)
self.s.close()
try:
self.c.close()
except:
s.connect((self.host,self.port))
s.close()
self.buttonswitch("0")
唯一的缺点是当我关闭连接时会引发有关管道损坏的错误。但这并不影响功能。
如果您有任何想法可以更正确,我很乐意学习,谢谢。
EDIT2:我将发布参考所涉及的所有代码:
from Tkinter import *
import socket, threading, time
import netifaces as ni
class Application(Frame):
def __init__(self, master):
""" Initialize the Frame"""
Frame.__init__(self,master)
self.grid()
self.create_widgets()
def create_widgets(self):
self.label1 = Label(text = "Target IPv6 address")
self.label1.grid(row=1, column=0)
self.entry1 = Entry(bd = 5)
self.entry1.grid(row=1, column = 1, columnspan = 2)
self.button1 = Button(text = "Start", command = lambda: self.threadcontrol("2"))
self.button1.grid(row=1, column = 3)
self.button2 = Button(text = "Start", command = lambda: self.threadcontrol("1"), state = DISABLED)
self.button2.grid(row=2, column=3)
self.button3 = Button(text = "Stop", command = lambda: self.serverstop("0"), state = DISABLED)
self.button3.grid(row=2, column=4)
self.button4 = Button(text = "Stop", command = lambda: self.clientstop("0"), state = DISABLED)
self.button4.grid(row=1, column=4)
self.label2 = Label(text = "Choose interface to listen")
self.label2.grid(row=2, column=0)
self.interfaces = Menubutton(text="------", relief=RAISED)
self.interfaces.grid(row=2, column=1, sticky="w")
self.interfaces.menu = Menu(self.interfaces, tearoff=0)
self.interfaces["menu"] = self.interfaces.menu
self.menubox()
self.label3 = Label(text = "")
self.label3.grid(row=2, column=2, sticky="w")
def menubox(self):
self.interfaces.menu.add_command(label="------", command = lambda interface="------": self.callback(interface))
for interface in ni.interfaces():
if interface.startswith('eth'):
self.interfaces.menu.add_command(label=interface, command = lambda interface=interface: self.callback(interface))
else:
pass
def callback(self, interface):
if interface.startswith('eth'):
self.intip = ni.ifaddresses(interface)[ni.AF_INET6][0]['addr']
self.interfaces["text"] = interface
if self.intip.startswith('fe80'):
self.label3["text"] = "No IPv6 address found"
self.button2["state"] = DISABLED
else:
self.label3["text"] = self.intip
self.button2["state"] = 'normal'
else:
self.interfaces["text"] = "------"
self.label3["text"] = ""
self.button2["state"] = DISABLED
def buttonswitch(self, flip):
if flip == "1":
# Disables server start button and enables server stop button.
self.button2["state"] = DISABLED
self.button3["state"] = "normal"
elif flip == "0":
# Disables server stop button and enables server start button
self.button3["state"] = DISABLED
self.button2["state"] = 'normal'
elif flip == "2":
# Enables client stop button
self.button4["state"] = 'normal'
elif flip == "3":
# Disables client stop button
self.button4["state"] = DISABLED
def threadcontrol(self, threadtype):
if threadtype == "1":
self.thread1 = threading.Thread(target = self.serverstart)
self.thread1.start()
elif threadtype == "2":
self.thread2 = threading.Thread(target = self.clientstart)
self.thread2.start()
else:
pass
def clientstop(self, status):
self.clientstatus = "1"
if status =="0":
self.clientstatus = status
def serverstop(self, status):
self.s.close()
def serverstart(self):
self.buttonswitch("1")
self.host = self.intip
self.port = 5000
self.s = socket.socket(socket.AF_INET6)
self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.s.bind((self.host, self.port))
self.s.listen(1)
self.c, addr = self.s.accept()
print "Connection from: " + str(addr)
while True:
data = self.c.recv(1500)
print len(data)
if not data:
break
data = str(data).upper()
self.c.send(data)
self.c.close()
self.s.close()
print "Closing socket"
self.buttonswitch("0")
def clientstart(self):
targetip = self.entry1.get()
host = targetip
port = 5000
s = socket.socket(socket.AF_INET6)
s.connect((host,port))
self.buttonswitch("2")
openfile = open('paskadata')
message = openfile.read()
self.clientstatus = "1"
status = self.clientstatus
n = 1
while status == "1":
s.send(message)
data = s.recv(1500)
status = self.clientstatus
print n
n = n + 1
time.sleep(50.0 / 1000)
s.close()
self.buttonswitch("3")
root = Tk()
root.title("IPv6 traffic generator")
root.geometry("450x200")
app = Application(root)
root.mainloop()
答案 0 :(得分:0)
问题是默认情况下accept
是阻止调用。除非队列中已存在待处理的连接,否则您实际上不会从accept
返回。
您可以使用gevent
之类的异步库,并启动一个单独的greenlet来处理用户界面事件。
或者,您可以使用套接字上的setblocking
方法直接将套接字设置为非阻塞。这将要求您使用轮询类型方法“重试”任何可能阻塞的套接字调用。
另一种类似的方法是使用settimeout
方法,如果其中任何一个花费太长时间,将导致阻塞操作超时。您可以将超时设置为合理的,例如50毫秒,人类不会被打扰并定期处理UI事件。同样,您需要在超时发生时重试阻塞套接字调用。
就个人而言,我更喜欢greenlet方法,因为它更简单。