在Python中定时UDP套接字

时间:2014-06-04 21:44:16

标签: python sockets

我是一个python新手,深入研究为Python 1.5编写的旧代码。它基本上实现了一个UDP服务器,用于读取客户端发送的数据。代码如下所示:

import socket
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
serverSocket.bind('localhost', 778)
msg, sndr = serverSocket.recvfrom(2048)

这个套接字的问题在于,如果客户端发送失败,它可以无限期地等待消息接收(我试图修复的bug的来源)。我知道从Python 2.3开始,可以使用settimeout方法,但不幸的是我必须坚持使用Python 1.5。如果有人可以帮助我使用代码片段/想法在这里拥有自己的超时功能,那就太棒了。

3 个答案:

答案 0 :(得分:3)

任何语言中的任何socket tutorial都会解释在套接字上设置超时的select调用。没有理由看基于纸莎草的蟒蛇。

答案 1 :(得分:1)

如果您没有找到任何其他解决方案,您可以尝试使用我之前写的这个超时装饰器。检查它是否有效

import ctypes
import threading
import time

class timeout:
    def __init__(self, timeout, kill_on_timeout=True):
        self.__timeout = timeout
        self.__kill_on_timeout = kill_on_timeout

    def __call__(self, func):
        def prep_func(*args, **kwargs):
            result = args[0]
            args = tuple(list(args)[1:])
            try:
                result.append(func(*args, **kwargs))
            except Exception as e:
                result.append(e)

        def timeout_func(*args, **kwargs):
            result = []
            args = tuple([result]+list(args))
            t = threading.Thread(target=prep_func, args=args, kwargs=kwargs)
            t.daemon = True
            t.start()
            timeout_time = self.__timeout+time.time()
            while True:
                if time.time()>=timeout_time:
                    if self.__kill_on_timeout:
                        try:
                            terminate_thread(t)
                        except:
                            raise TimeoutReached('Could not kill the thread!')
                    raise TimeoutReached('Timeout reached! Thread killed.')
                if result:
                    if not issubclass(type(result[0]), BaseException):
                        return result[0] 
                    raise result[0]
                time.sleep(0.001)
        return timeout_func


def terminate_thread(thread):
    if not thread.isAlive():
        return None
    exc = ctypes.py_object(SystemExit)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(
        ctypes.c_long(thread.ident), exc)
    if res == 0:
        raise ValueError('err')
    elif res > 1:
        ctypes.pythonapi.PyThreadState_SetAsyncExc(thread.ident, None)
        raise SystemError('err')

class TimeoutReached(Exception):
    pass

答案 2 :(得分:0)

好的,我通过使用select模块找到了解决此问题的方法。

代码现在看起来如下:

import socket, select
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
serverSocket.bind('localhost',778)
while running:    #running variable is set to True
    incoming = select.select([serverSocket],[],[],5) #5 corresponds to timeout in seconds
    try:
        msg,sndr = incoming[0][0].recvfrom(2048)
    except IndexError:
        sys.stderr.write('Timed out in receiving message on UDP server')
        continue