2014-12-13 1 views
1

들어오는 연결을 수신하는 소켓이 있고 설정이 완료되고 데이터가 이동하면 버튼을 사용하여 연결을 닫을 수 있지만 연결이 설정되고 while 루프가 시작되기 전에 버튼을 사용하여 소켓을 중지 할 수 있습니까? 내가 활성화 및 정지를 해제하고 서버의 상태와수신 대기 중이지만 아직 연결을 수락하지 않은 소켓을 닫는 방법

편집을 연계하여 버튼을 시작 buttonswitch 기능을 사용

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

: 여기

이 소켓의 코드 나는 없앴다고 대신이 추가 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

내가 어떻게 작동하는지 이해가 안됩니다. GUI가 서버와 다른 스레드에서 실행 중이 더라도 서버가 메시지를 처리하는 동안'self.serverstatus'를 수정할 수 있습니다.'recv'에서 차단되면 여전히 효과가 없을 것입니다. 또는'보내기'. – abarnert

+0

어쨌든's'와'c' 멤버 변수 만 만들면 항상'self.s.close()'와'self.c.close()'를 호출 할 수 있습니다 (먼저 존재하는지 확인하십시오.), 나는 그 소켓에서'accept','recv','send'를 막고 EBADFD','ECONNRESET', 또는'EINTR'를 발생시키는 것을 확실히 막을 것이라고 확신합니다. – abarnert

+0

self.sc.close()를 사용하여 연결을 종료 한 후 self.sc.close()를 사용하여 연결을 닫을 수있는 동안 변수를 self.s 및 self.c로 각각 변경하려고 시도했지만, 소켓이 연결을 기다리지 않게하십시오. – Nyoa

답변

0

문제는 accept는 기본적으로 차단 호출 있다는 것이다 : 나는 참조 관련된 모든 코드를 게시 할 수 있습니다. 대기열에 대기중인 연결이 이미있는 경우가 아니면 실제로 accept에서 돌아 오지 않습니다.

gevent과 같은 비동기 라이브러리를 사용하고 사용자 인터페이스 이벤트를 처리하는 개별 Greenlet을 시작할 수 있습니다.

또는 소켓에서 setblocking 메서드를 사용하여 소켓을 직접 비 차단으로 설정할 수 있습니다. 이렇게하려면 폴링 유형 메소드를 사용하여 잠재적으로 블로킹 소켓 호출을 "다시 시도"해야합니다.

또 다른 유사한 접근 방법은 settimeout 메서드를 사용하는 것입니다.이 메서드는 차단 작업이 너무 오래 걸리는 경우 시간 초과가 발생할 수 있습니다. 휴먼이 방해받지 않고 UI 이벤트를 주기적으로 처리 할 수 ​​있도록 50 밀리 초와 같은 합리적인 것으로 타임 아웃을 설정할 수 있습니다. 다시 말하지만, 시간 제한이 발생할 때 블로킹 소켓 호출을 다시 시도해야합니다.

개인적으로 그린렛 접근법은 개인적으로는 훨씬 간단하기 때문에 선호합니다.

+0

그러나'recv' (와'send')도 마찬가지입니다. 그래서 수신 할 데이터가 없다면 그의 버튼도 거기에서 작동하지 않을 것입니다. – abarnert

+0

사실,하지만 내 대답은 모든 소켓 작업을 비 차단 방식으로 만드는 것입니다. – b4hand

+0

그 당시 나는 그것을 쓰지 않았다. 그러나 요점은 우리가 그것을 받아 들일 수 있는지 또는 그가 디자인을 완전히 바꾸어야하는지 여부를 설명하기 전에 그의 버튼이 어떻게/왜 왜 작동 하는지를 알 필요가 있다는 것입니다. – abarnert

관련 문제