2013-05-24 40 views
6

Tôi gặp sự cố khi tìm hiểu về ổ cắm cho giao tiếp mạng. Tôi đã tạo một luồng đơn giản để lắng nghe các kết nối và tạo ra các quy trình để kết nối các máy khách, mặc dù vấn đề của tôi là tôi không thể lấy chủ đề để tham gia đúng như tôi đã không tìm thấy cách hủy lệnh socket.accept() - khi tôi muốn bỏ chương trình.Đóng ổ cắm nghe trong chủ đề python

Mã của tôi trông như thế này;

class ServerThread(threading.Thread): 

    def __init__(self, queue, host, port): 
     threading.Thread.__init__(self) 
     self.queue = queue 
     self.running = True 
     self.hostname = host 
     self.port = port 

    def run(self): 
     self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.socket.bind((self.hostname, self.port)) 
     self.socket.listen(1) 
     while self.running: 
      try: 
       conn, address = self.socket.accept() 
       process = Process(target=server_slave, args=(conn, address, self.queue)) 
       process.daemon = True 
       process.start() 
      except socket.timeout: 
       pass 

    def stop(self): 
     self.running = False 
     self.socket.close() 

tôi đã được quản lý để có được những chương trình để đóng bằng cách thiết lập self.setDaemon(True) và chỉ thoát khỏi chương trình chính, bàn giao tất cả mọi thứ để thu gom rác tuyệt vời - nhưng điều đó dường như là một giải pháp xấu. Tôi cũng đã cố gắng thiết lập một thời gian chờ cho các ổ cắm nhưng kết quả trong việc [Errno 35] Resource temporarily unavailable (bất kể thời gian chờ thực tế, ngay cả khi tôi đặt nó đến năm ...).

Tôi đang làm gì sai? Tôi đã thiết kế các chủ đề một cách câm hoặc có tôi bị mất một cái gì đó về việc chấp nhận các kết nối?

+0

'nhưng điều đó dường như là một giải pháp xấu' - nó hoạt động? Nếu bạn không thích có hệ điều hành chấm dứt tất cả các chủ đề của bạn, bạn có thể thử đóng các ổ cắm nghe từ chính, hoặc chủ đề khác. Điều đó thường làm cho accept() trả về 'sớm' với một lỗi. Hoạt động trên hầu hết các hệ điều hành/ngôn ngữ, nhưng không được thử bằng Python, vì vậy không phải là câu trả lời. –

+0

Nó hoạt động - nhưng tôi có cảm giác tôi có thể không đối xử với khách hàng tiềm năng rất tốt trong việc đó. Tôi đã đăng một giải pháp có vẻ đẹp hơn vì nó cho phép mã hoàn thành, nhưng nó vẫn có vẻ hơi lạ vì nó kết thúc bằng cách tạo một quy trình mới mà tôi sẽ phải tham gia ngay lập tức. – Norling

Trả lời

8

Một cách để làm cho chuỗi đóng lại dường như là tạo kết nối với ổ cắm, do đó tiếp tục hoàn thành chuỗi.

def stop(self): 
    self.running = False 
    socket.socket(socket.AF_INET, 
        socket.SOCK_STREAM).connect((self.hostname, self.port)) 
    self.socket.close() 

này hoạt động, nhưng nó vẫn cảm thấy như nó có thể không được tối ưu ...

+0

Có - 'giả tạo' thỏa mãn điều kiện chờ, (như ở đây - mở một kết nối tạm thời cục bộ), cũng nằm trong thủ thuật 'chặn chủ đề bị chặn'. –

+0

Bạn dường như biết công cụ này! ^^ Cảm ơn sự giúp đỡ! Bất kỳ thủ đoạn nào khác tôi có thể thử? – Norling

+0

Hiện đang cố gắng hiểu vấn đề/mã này - tôi đã làm như vậy nhưng tôi không thể lấy đầu của tôi xung quanh "socket, .socket (socket.AF_INET ...) line - mục đích của nó là gì? – Kev1n91

0

Trong hầu hết các trường hợp, bạn sẽ mở một chủ đề mới hoặc quá trình một lần kết nối được chấp nhận. Để đóng kết nối, hãy ngắt vòng lặp while. Bộ sưu tập rác sẽ loại bỏ các chủ đề hoặc quá trình nhưng tham gia sẽ đảm bảo không có được bỏ lại phía sau.

Ổ cắm liên tục đóng khi người dùng đóng cửa hoặc họ hết thời gian chờ. Không liên tục, giống như các trang web tĩnh sẽ đóng lại sau khi chúng đã gửi thông tin.

Đây là một ví dụ điển hình về máy chủ socket liên tục trong Python. Nó sử dụng đa xử lý có nghĩa là nó có thể chạy trên nhiều lõi cho các nhiệm vụ ràng buộc CPU. Thường được gọi là đa luồng.

import socket 
import multiprocessing 

def run(): 
    host = '000.000.000.000' 
    port = 1212 
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
    sock.bind(('', port)) 
    sock.listen(3) 
    while True: 
     p = multiprocessing.Process(target=worker, args=sock.accept()).start() 
def worker(conn, addr): 
    while True: 
     if data == '': 
      #remote connection closed 
      break 
     if len(dataList) > 2: 
      # do stuff 
      print 'This code is untested' 

run() 
-1

một phần thử nghiệm giải pháp

  1. Đặt self.socket.settimeout(0.1) ngay trước while
  2. Đặt conn.settimeout(None) ngay sau khi accept
+4

Làm theo lời khuyên này là quyết định tồi tệ nhất mà tôi đã thực hiện cả ngày – Paradoxis

+0

Tôi tìm thấy 'settimeout()' để làm việc cho tôi, xem http://stackoverflow.com/a/41643863/143931. – fuenfundachtzig

Các vấn đề liên quan