rtmp.py & orphaned connections

22 views
Skip to first unread message

msp...@gmail.com

unread,
Dec 27, 2015, 4:40:20 AM12/27/15
to myprojectguide

 Hi, 

 I am running rtmp.py with VideoIO.swf in a multi party conference configuration. So far everything has gone well with an exception. Once in a while a party broadcasting with a poor connection will drop hard and it seems rtmp.py is not detecting this so the sockets appear orphaned without any way to remove them (I have to kill the server). I know very little Python so i'm not finding my way around the code very well. As long as the connection remains on, for example, mount point 'live1', no other user can use it. This is obviously not ideal as the mount points are hard coded for the publisher swf. So situations such as these render a camera unusable until the server is restarted.

  I would think a routine to check stream states for data every X amount of time or close() would be ideal? Any guidance would be appreciated. Thanks!

 

Intencity Team

unread,
Dec 27, 2015, 12:59:58 PM12/27/15
to myproje...@googlegroups.com, msp...@gmail.com
Hi,

One thing you can try first is to add TCP keepalive after line 946 in rtmp.py:
The TCP keepalive code is shown in 
look for the answer with most points (~20).
If you are new to Python, make sure to keep the indentation correct.
I think a keepalive of 1 min should be okay, but of a few seconds may be too aggressive.

I expect that if keepalive is enabled, then the server will receive the TCP close signal if the publishing client is unresponsive.

If this does not work then we can create a application level keep alive using RTMP RPC.

Hope this helps!


--
--
You received this message because you are subscribed to the Google
Groups "myprojectguide" group.
To post to this group, send email to myproje...@googlegroups.com
To unsubscribe from this group, send email to
myprojectguid...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/myprojectguide?hl=en

---
You received this message because you are subscribed to the Google Groups "myprojectguide" group.
To unsubscribe from this group and stop receiving emails from it, send an email to myprojectguid...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
The Intencity Team  http://theintencity.com

msp...@gmail.com

unread,
Dec 27, 2015, 8:45:47 PM12/27/15
to myprojectguide, msp...@gmail.com
UPDATE:

 Removed the line 'import socket' and it's running now. Looking at the preceding lines I guess it's safe to assume it was already imported somewhere. Code now looks like:

###############################################

     def run(self):
        try:
            while True:
                sock, remote = (yield multitask.accept(self.sock))  # receive client TCP
                if sock == None:
                    if _debug: print 'rtmp.Server accept(sock) returned None.'
                    break
                if _debug: print 'connection received from', remote
                sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) # make it non-block
                def set_keepalive_linux(sock, after_idle_sec=20, interval_sec=30, max_fails=2):
                    sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
                    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, after_idle_sec)
                    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, interval_sec)
                    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, max_fails)
                client = Client(sock, self)
        except GeneratorExit: pass # terminate
        except:
            if _debug: print 'rtmp.Server exception ', (sys and sys.exc_info() or None)

        if (self.sock):
            try: self.sock.close(); self.sock = None
            except: pass
        if (self.queue):
            yield self.queue.put((None, None))
            self.queue = None

#################################################

 I don't know if it's actually doing anything, it's a wait and see process unless you see something wrong with my code insert. I'll follow up if not on how effective this was so it's helpful to others. Thanks!

msp...@gmail.com

unread,
Dec 27, 2015, 8:45:48 PM12/27/15
to myprojectguide, msp...@gmail.com

 Thanks for the response on this. Here is how I planted the snippet (Note I omitted the *osx portion of the stack example as I am on linux):

##################################################################

def run(self):
        try:
            while True:
                sock, remote = (yield multitask.accept(self.sock))  # receive client TCP
                if sock == None:
                    if _debug: print 'rtmp.Server accept(sock) returned None.'
                    break
                if _debug: print 'connection received from', remote
                sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) # make it non-block
                import socket
                def set_keepalive_linux(sock, after_idle_sec=20, interval_sec=30, max_fails=2):
                    sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
                    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, after_idle_sec)
                    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, interval_sec)
                    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, max_fails)
                client = Client(sock, self)
        except GeneratorExit: pass # terminate
        except:
            if _debug: print 'rtmp.Server exception ', (sys and sys.exc_info() or None)

        if (self.sock):
            try: self.sock.close(); self.sock = None
            except: pass
        if (self.queue):
            yield self.queue.put((None, None))
            self.queue = None


###########################################################

 The server starts and runs without error but when I try to connect a broadcaster now I get:

###########################################################


rtmp$ python rtmptest.py -d
listening on  ('0.0.0.0', 1935)
Sun Dec 27 15:21:48 2015 Flash Server Starts - 0.0.0.0:1935
connection received from ('192.168.1.1', 1296)
rtmp.Server exception  (<type 'exceptions.UnboundLocalError'>, UnboundLocalError("local variable 'socket' referenced before assignment",), <traceback object at 0xb714439c>)
Sun Dec 27 15:21:54 2015 Flash Server Stops
rtmp$


##################################################################

 I suspect I'm doing something wrong :)

 Thanks!


On Sunday, December 27, 2015 at 12:59:58 PM UTC-5, Intencity Cloud Technologies wrote:

msp...@gmail.com

unread,
Dec 28, 2015, 2:00:53 PM12/28/15
to myprojectguide, msp...@gmail.com

 UPDATE #2

 I got home tonight to another stuck client. Looking at my netstat output I see no keepalive sockets (doh!) So I re-examined my insertion and came to the deduction that i'm too noob to get it right the first, or even second time. But I think I nailed it this time. The following implementation yields a running server spawning keepalive sockets.

###################################################

    def run(self):
        try:
            while True:
                sock, remote = (yield multitask.accept(self.sock))  # receive client TCP
                if sock == None:
                    if _debug: print 'rtmp.Server accept(sock) returned None.'
                    break
                if _debug: print 'connection received from', remote
                sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) # make it non-block
                sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
                sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 10)
                sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 10)
                sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 2)
                client = Client(sock, self)
        except GeneratorExit: pass # terminate
        except:
            if _debug: print 'rtmp.Server exception ', (sys and sys.exc_info() or None)

        if (self.sock):
            try: self.sock.close(); self.sock = None
            except: pass
        if (self.queue):
            yield self.queue.put((None, None))
            self.queue = None

##########################################

 I'll update after a few smooth days. Thanks for the pointers!




On Sunday, December 27, 2015 at 12:59:58 PM UTC-5, Intencity Cloud Technologies wrote:

msp...@gmail.com

unread,
Dec 31, 2015, 1:35:54 PM12/31/15
to myprojectguide, msp...@gmail.com

 UPDATE #3

 Just wanted to follow up. The code provided in update #2 is working well. No more lingering connections. Thanks for all the help!



On Sunday, December 27, 2015 at 12:59:58 PM UTC-5, Intencity Cloud Technologies wrote:
Reply all
Reply to author
Forward
0 new messages