Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何关闭正在侦听但尚未接受连接的套接字_Python_Sockets_User Interface - Fatal编程技术网

Python 如何关闭正在侦听但尚未接受连接的套接字

Python 如何关闭正在侦听但尚未接受连接的套接字,python,sockets,user-interface,Python,Sockets,User Interface,我有一个监听传入连接的套接字,一旦连接建立且数据移动,我就可以使用按钮关闭连接,但我是否可以在连接建立和while循环开始之前使用按钮停止套接字 以下是套接字的代码: def serverstart(self): self.buttonswitch("1") host = self.intip port = 5000 s= socket.socket(socket.AF_INET6) s.sets

我有一个监听传入连接的套接字,一旦连接建立且数据移动,我就可以使用按钮关闭连接,但我是否可以在连接建立和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变量并添加了这个变量(创建到套接字的连接以关闭它):

唯一的缺点是,当我关闭一个连接时,它会引发一个关于管道破裂的错误。但这并不影响功能

如果你对此有任何更正确的想法,我很乐意学习,谢谢

编辑2:我将发布所有相关代码以供参考:

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()

问题在于默认情况下,
accept
是一个阻塞调用。除非队列上已经存在挂起的连接,否则您实际上不会从
accept
返回

您可以使用一个异步库,例如,启动一个单独的greenlet,在其中处理用户界面事件

或者,您可以使用套接字上的方法直接将套接字设置为非阻塞。这将要求您使用轮询类型方法“重试”任何可能阻塞的套接字调用

另一种类似的方法是使用这种方法,如果阻塞操作中的任何一个花费的时间太长,就会导致阻塞操作超时。您可以将超时时间设置为合理的值,比如50毫秒,这样人类就不会被打扰,并定期处理UI事件。同样,当超时发生时,您需要重试阻塞套接字调用


就个人而言,我更喜欢greenlet方法,因为它简单得多。

但是
recv
(和
send
)也是如此,所以如果没有数据接收,他的按钮也不会在那里工作。是的,但我的答案是让所有套接字操作都以这种或那种方式不阻塞。在我写这篇文章的时候没有。但我的观点是,我们需要知道他的按钮是如何/为什么工作的,然后才能解释是否有可能使其在
accept
上工作,或者他是否必须完全更改其设计。我的按钮将self.serverstatus状态更改为0,这足以停止while循环。我正在制作一个适用于IPv6的数据包生成器,因此一旦连接启动,循环就会在一秒钟内迭代数千次。唯一的问题是,在客户端连接到套接字之前,我需要其他方法来关闭它。对于您的最后一次编辑,使用
settimeout
并像那样重试通常比仅使用
select
(或者,如果您使用的是3.4+,则使用
选择器
模块,这稍微简单一些)更复杂和复杂1.我不明白你怎么会期望这样。即使GUI在与服务器不同的线程中运行,因此它可以在服务器忙于处理消息时修改self.serverstatus,但如果您在
recv
send
上被阻止,这仍然不会产生任何影响。无论如何,如果您只需要创建
s
c
成员变量,您总是可以调用
self.s.close()
self.c.close()
(首先检查它们是否存在,如果合适的话),我很确定这会中断该套接字上的任何阻塞
accept
recv
send
,并使其引发
EBADFD
ECONNRESET
,或
EINTR
。我试图分别将变量更改为self.s和self.c,但虽然我能够在连接启动后使用self.c.close()关闭连接,但使用self.s.close()并没有阻止套接字侦听连接。在编辑的版本中,您仍然使用局部变量
s
,非
self.s
。另外,我刚才向您解释了
self.c.close()
将使阻塞的
recv
引发
ECONNRESET
或类似错误,因此我不确定您为什么对它引发错误感到惊讶。更重要的是,您仍然必须向我们解释如何并行运行GUI和服务器。您是否为每个线程使用单独的线程?或者类似于
gevent
?还是怎样因为你必须要做点什么。
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()