8

Good day! I was writen simple server:

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)

How to set connection timeout. I want when the client not send me data and is not active in 30 seconds, server will close connection.

P.S. sorry for my english.

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

2 Answers 2

7

If you use StreamRequestHandler instead of BaseRequestHandler, you just need to override the timeout variable there, and it will be set. If you want to learn how to do it yourself, just look at the SocketServer.py

Here's an example, this will kill any connections that aren't done in 5 seconds:

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

This uses the python's socket settimeout() call.

I don't think your alarm() solution will work with threading or forking.

0
3

Please look at it:

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

If you want to handle more than one request you need to execute server.handle_request() again.

5
  • This is not work for me. I started server as a deamon in linux. Wen i set server.handle_request() , server not answer :/$ telnet localhost 43 Trying ::1... Trying 127.0.0.1... telnet: Unable to connect to remote host: Connection refused Commented Aug 18, 2011 at 14:15
  • I decided my problem to set alarm (5) in the handle method Commented Aug 18, 2011 at 15:00
  • You cant connect on port 43 because server is listening on port 6666. I can't know what you have in settings because you didn't attached this part of code.
    – Adam
    Commented Aug 18, 2011 at 16:19
  • no, server listen 43 port. I am not copy past yours listing code, I copy only server.handle_request, handle_timeout function, timeout = 30 and my deamon start and stopped. Wen i added while 1 , in my running function. the server was answer, but this is not what I want, becose I can not stopped connection. Alarm is stopped connection for me. Commented Aug 18, 2011 at 21:28
  • Please update your question and code there. I'm not sure how it looks right now.
    – Adam
    Commented Aug 19, 2011 at 14:26

Not the answer you're looking for? Browse other questions tagged or ask your own question.