8

良い一日!私は単純なサーバーを書きました:

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 秒以内にアクティブでない場合、サーバーは接続を閉じます。

PS私の英語でごめんなさい。

アップデート

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

2 に答える 2

7

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 のソケット settimeout()呼び出しを使用します。

alarm()あなたのソリューションがスレッド化やフォークで機能するとは思いません。

于 2012-10-24T17:30:46.970 に答える
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() を再度実行する必要があります。

于 2011-08-18T13:06:44.340 に答える