2011-08-18 18 views
7

おはよう!私はシンプルなサーバーを書かれました: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) 

接続タイムアウトを設定する方法。クライアントがデータを送信せず、30秒でアクティブでない場合、サーバーは接続を終了します。

P.S.私の英語のために申し訳ありません。

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

答えて

3

それを見てください:

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 

あなたは再び)(server.handle_requestを実行する必要が複数の要求を処理します。

+0

これは私の仕事ではありません。私はLinuxでdeamonとしてサーバを起動しました。私はserver.handle_request()を設定しました。サーバは応答しません:/ $ telnet localhost 43 試行中:: 1 ... 試行中127.0.0.1 ... telnet:リモートホストに接続できません:Connection refused – user900281

+0

問題がハンドルメソッドでアラーム(5)を設定するには – user900281

+0

サーバーがポート6666でリッスンしているため、ポート43で接続できません。このコード部分が添付されていないため、設定内容を知ることができません。 – Adam

6

BaseRequestHandlerの代わりにStreamRequestHandlerを使用する場合は、そこにあるタイムアウト変数をオーバーライドするだけで設定されます。あなたはそれを自分で行う方法を学習したい場合は、単にSocketServer.py

を見てここでは一例ですが、これは5秒で行われていないすべての接続殺す:

#!/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() 

をこれは使用していますPythonのsocket settimeout()呼び出し。

あなたのalarm()ソリューションは、スレッドやフォークでは機能しません。

関連する問題