root/livinglogic.python.tipimaid/liaalh_sender.py @ 49:6ce0aee574f5

Revision 49:6ce0aee574f5, 2.7 KB (checked in by Nikolas Tautenhahn <nik@…>, 11 years ago)

proper handling of lost connections

Line 
1import sys, socket, select, signal, datetime
2
3def intify(s, defaultint=0):
4    try:
5        return int(s)
6    except ValueError, exc:
7        return defaultint
8
9class Sender(object):
10    def __init__(self, ip, port, backupport, stream=sys.stdin):
11        self.ip = ip
12        self.port = port
13        self.backupport = backupport
14        self.stream = stream
15        self.check_every = datetime.timedelta(seconds=10)
16        self.s = None
17        self.create_socket()
18        self.last_check_connection = datetime.datetime.now()
19        signal.signal(signal.SIGALRM, self.timeout)
20
21    def readlines(self):
22        while True:
23            try:
24                line = self.stream.readline()
25            except IOError, exc:
26                if exc[0] == errno.EINTR:
27                    continue
28                else:
29                    raise
30            if not line:
31                break
32            yield line
33
34    def create_socket(self):
35        if self.s is None:
36            for (af, socktype, proto, canonname, sa) in socket.getaddrinfo(self.ip, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM):
37                try:
38                    s = socket.socket(af, socktype, proto)
39                except socket.error, msg:
40                    s = None
41                    continue
42                try:
43                    s.connect(sa)
44                except socket.error, exc:
45                    s.close()
46                    s = None
47                    continue
48                break
49            self.s = s
50
51    def timeout(self, signum, frame):
52        raise socket.timeout
53
54    def send_socket(self, line):
55        (l, t) = (len(line), 0)
56        while t < l: # it might be that only a part of line gets transmitted
57            t += self.s.send(line[t:])
58            signal.alarm(5) # wait 5 seconds for server to notify us that it got the message
59            try:
60                if self.s.recv(1024) == "":
61                    raise socket.timeout
62            except (socket.timeout, socket.error), exc:
63                print "Could not send", line # Handle error
64                self.s.close()
65                self.s = None
66                self.last_check_connection = datetime.datetime.now()
67            signal.alarm(0)
68
69    def send_tempfile(self, line):
70        print "Writing ", line
71        td = datetime.datetime.now() - self.last_check_connection
72        if td > self.check_every:
73            print "Checking..."
74            self.create_socket()
75            self.last_check_connection = datetime.datetime.now()
76            if self.s:
77                print "We have a new connection!"
78
79    def send(self):
80        for line in self.readlines():
81            if self.s:
82                self.send_socket(line)
83            else:
84                self.send_tempfile(line)
85        if self.s:
86            self.s.close()
87
88def main(args=None):
89    import optparse
90    p = optparse.OptionParser(usage="usage: %prog ip port [options]")
91    p.add_option("-b", "--backupport", dest="backupport", type="int", action="store", help="Recovery port", default=None)
92    (options, args) = p.parse_args()
93    if len(args) != 2 or intify(args[1], None) is None:
94        p.print_usage(sys.stderr)
95        sys.stderr.write("%s: We need an IP and a port\n" % p.get_prog_name())
96        sys.stderr.flush()
97        return 1
98    S = Sender(args[0], intify(args[1], None), options.backupport)
99    S.send()
100
101
102if __name__ == "__main__":
103    sys.exit(main())
Note: See TracBrowser for help on using the browser.