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

时间:2014-12-13 04:33:30

标签: python sockets user-interface

我有一个侦听传入连接的套接字,一旦建立并且数据移动,我就可以使用按钮关闭连接,但是我可以使用按钮来停止连接甚至在建立连接和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()

1 个答案:

答案 0 :(得分:0)

问题是默认情况下accept是阻止调用。除非队列中已存在待处理的连接,否则您实际上不会从accept返回。

您可以使用gevent之类的异步库,并启动一个单独的greenlet来处理用户界面事件。

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

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

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