2011-08-18 16 views
7

Buona giornata! Sono stato scritto server semplice:Come creare il timeout della connessione con python SocketServer

class SingleTCPHandler(SocketServer.BaseRequestHandler): 

    def handle(self): 
     data = self.request.recv(1024) 
     self.request.close() 

class SimpleServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): 

    daemon_threads = True 

    allow_reuse_address = True 

    def __init__(self, server_address, RequestHandlerClass): 
     SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass) 


def running(): 
    server = SimpleServer((settings.host, settings.port), SingleTCPHandler) 
    try: 
     server.serve_forever() 
    except KeyboardInterrupt: 
     sys.exit(0) 

Come impostare il timeout della connessione. Voglio quando il client non mi invia dati e non è attivo in 30 secondi, il server chiuderà la connessione.

P.S. mi scusi per il mio inglese.

UPDATE

#!/usr/bin/env python 
# -*- coding: utf8 -*- 

import sys 
import time 

import SocketServer 
import datetime 
import settings 
import os 
from signal import SIGTERM, SIGCHLD, signal, alarm 
import socket 
import subprocess 
from threading import Thread 
import MySQLdb 
import re 

class SingleTCPHandler(SocketServer.BaseRequestHandler): 
    "One instance per connection. Override handle(self) to customize action." 
    def handle(self): 
     alarm(30) 
     data = self.request.recv(1024) 
     # Some code 
     self.request.close() 


class SimpleServer(SocketServer.ForkingMixIn, SocketServer.TCPServer): 

    daemon_threads = True 
    allow_reuse_address = True 


    def __init__(self, server_address, RequestHandlerClass): 
     SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass) 




def running(): 
    server = SimpleServer((settings.host, settings.port), SingleTCPHandler) 
    try: 
     server.serve_forever() 
    except KeyboardInterrupt: 
     sys.exit(0) 


def deamonize(stdout='/dev/null', stderr=None, stdin='/dev/null', pidfile=None, startmsg='started with pid %s'): 
    try: 
     pid = os.fork() 
     if (pid > 0): 
      sys.exit(0) 
    except OSError, e: 
     sys.stderr.write("fork #1 failed: (%d) %s\n" % (e.errno, e.strerror)) 
     sys.exit(1) 

    os.chdir(settings.place) 
    os.umask(0) 
    os.setsid() 

    try: 
     pid = os.fork() 
     if (pid > 0): 
      sys.exit(0) 
    except OSError, e: 
     sys.stderr.write("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror)) 
     sys.exit(1) 

    if (not stderr): 
     stderr = stdout 

     print stdin, stdout, stderr 
     si = file(stdin, 'r') 
     so = file(stdout, 'a+') 
     se = file(stderr, 'a+', 0) 
     pid = str(os.getpid()) 
     sys.stderr.write("\n%s\n" % startmsg % pid) 
     sys.stderr.flush() 
    if pidfile: file(pidfile, 'w+').write("%s\n" % pid) 

    os.dup2(si.fileno(), sys.stdin.fileno()) 
    os.dup2(so.fileno(), sys.stdout.fileno()) 
    os.dup2(se.fileno(), sys.stderr.fileno()) 

def startstop(stdout='/dev/null', stderr=None, stdin='/dev/null', pidfile='pid.txt', startmsg='started with pid %s'): 
    if len(sys.argv) > 1: 
     action = sys.argv[1] 
     try: 
      pf = open(pidfile) 
      pid = int(pf.read().strip()) 
      pf.close() 
     except IOError: 
      pid = None 
     if ((action == 'stop') or (action == 'restart')): 
      if (not pid): 
       mess = "Не могу остановить, pid файл '%s' отсутствует.\n" 
       sys.stderr.write(mess % pidfile) 
       sys.exit(1) 
      try: 
       while 1: 
        os.kill(pid, SIGTERM) 
        time.sleep(1) 
      except OSError, err: 
       err = str(err) 
       if err.find("No such process") > 0: 
        os.remove(pidfile) 
        if 'stop' == action: 
         sys.exit(0) 
        action = 'start' 
        pid = None 
       else: 
        print str(err) 
        sys.exit(1) 
     if ('start' == action): 
      if (pid): 
       mess = "Старт отменен — pid файл '%s' существует.\n" 
       sys.stderr.write(mess % pidfile) 
       sys.exit(1) 
      deamonize(stdout, stderr, stdin, pidfile, startmsg) 
      return 
    print "Синтакс запуска: %s start|stop|restart" % sys.argv[0] 
    sys.exit(2) 

if (__name__ == "__main__"): 
    startstop(stdout=settings.log, pidfile=settings.pid) 
    running() 

risposta

3

Si prega di vedere le cose:

import sys 
import SocketServer 

class SingleTCPHandler(SocketServer.BaseRequestHandler): 
    def handle(self): 
     data = self.request.recv(1024) 
     self.request.close() 

class SimpleServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): 

    timeout = 30 

    daemon_threads = True 
    allow_reuse_address = True 

    def __init__(self, server_address, RequestHandlerClass): 
     SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass) 

    def handle_timeout(self): 
     print 'Timeout!' 


def running(): 
    server = SimpleServer(('localhost', 6666), SingleTCPHandler) 
    try: 
     #server.serve_forever() 
     server.handle_request() 
    except KeyboardInterrupt: 
     sys.exit(0) 

if __name__ == '__main__': 
    running() 

# vim: filetype=python syntax=python expandtab shiftwidth=4 softtabstop=4 encoding=utf8 

Se si desidera gestire più di una richiesta è necessario eseguire nuovamente() server.handle_request.

+0

Questo non è lavoro per me. Ho avviato il server come deamon in linux. Wen ho impostato server.handle_request(), server non risponde:/$ telnet localhost 43 Provare :: 1 ... Provare 127.0.0.1 ... telnet: Impossibile connettersi all'host remoto: Connessione rifiutata – user900281

+0

Ho deciso il mio problema per impostare l'allarme (5) nel metodo handle – user900281

+0

Non è possibile connettersi sulla porta 43 perché il server è in ascolto sulla porta 6666. Non posso sapere cosa si ha nelle impostazioni perché non è stata collegata questa parte di codice. – Adam

6

Se si utilizza StreamRequestHandler invece di BaseRequestHandler, è sufficiente eseguire l'override della variabile di timeout e verrà impostato. Se volete imparare a fare da soli, basta guardare la SocketServer.py

Ecco un esempio, questo ucciderà tutte le connessioni che non sono fatto in 5 secondi:

#!/usr/bin/env python 
import SocketServer 

class myHandler(SocketServer.StreamRequestHandler): 
    timeout = 5 
    def handle(self): 
     recvdata = "" 
     while True: 
      tmp = self.request.recv(16384) 
      recvdata = recvdata + tmp.strip() 
      if (len(tmp) < 16384): 
       break; 
     self.request.send("Received: {0}".format(recvdata)) 

class myApp(SocketServer.TCPServer): 

    def __init__(self): 
     SocketServer.TCPServer.__init__(self, ("localhost", 5555), myHandler) 
     print self.server_address 
     try: 
      self.serve_forever() 
     except KeyboardInterrupt: 
      print "Got keyboard interrupt, shutting down" 
      self.shutdown() 

if __name__ == "__main__": 
    app = myApp() 

Questo utilizza la chiamata socket settimeout() di python.

Non penso che la tua soluzione alarm() funzionerà con threading o forking.