Search code examples
pythonsocketsasyncsocketasyncore

Python - Asyncore (client) socket - Can not determaine connection status


For some reason, self.connected of the asyncore.dispatcher class doesn't consider my socket to be connected on the client side. The server side sees the socket as connected and treats it as such, but the client doesn't know if it's connected or not and handle_connect doesn't "proc", so i can't use a overridden version of it to check if the socket is connected either.

Any thoughts on this code why it ain't working:

#!/usr/bin/python
# -*- coding: iso-8859-15 -*-
import asyncore
from threading import *
from socket import *
from time import sleep
from os import _exit
from logger import *
from config import *

class logDispatcher(asyncore.dispatcher):
    def __init__(self, config=None):
        self.inbuffer = ''
        self.buffer = ''
        self.lockedbuffer = False
        self.is_writable = False

        asyncore.dispatcher.__init__(self)
        #Thread.__init__(self)

        self.create_socket(AF_INET, SOCK_STREAM)

        #self.is_writable = True
        #self.start()

    def compare(self, obj, otherobj):
        return (str(obj).lower() == str(otherobj).lower()[:len(str(obj))])
    def _in(self, obj, otherobj):
        return (str(obj).lower() in str(otherobj).lower())

    def parse(self):
        if self.inbuffer[-2:] != '\r\n':
            return False

        self.lockedbuffer = True
        self.inbuffer = ''
        self.lockedbuffer = False

    def readable(self):
        return True

    def handle_connect(self):
        log('Connected to ' + str(server), 'SOCK_CORE')

    def handle_close(self):
        self.close()

    def handle_read(self):
        data = self.recv(8192)
        while self.lockedbuffer:
            sleep(0.01)
        self.inbuffer += data

    def writable(self):
        return (len(self.buffer) > 0)

    def handle_write(self):
        while self.is_writable:
            sent = self.send(self.buffer)
            sleep(1)
            self.buffer = self.buffer[sent:]
            if len(self.buffer) <= 0:
                self.is_writable = False
            sleep(0.01)

    def _send(self, what):
        self.buffer += what + '\r\n'
        self.is_writable = True

    def handle_error(self):
        log('Error, closing socket!', 'SOCK_CORE')
        self.close()

    def run(self):
        log('Log socket engine initating', 'SOCK_CORE')
        self.connect((server, server_port))

        print self.connected
        sleep(3)
        print self.connected

class start(Thread):
    def __init__(self):
        Thread.__init__(self)
        self.start()
    def run(self):
        asyncore.loop(0.1)

start()
logDisp = logDispatcher()
logDisp.run()

Solution

  • def handle_connect_event(self):
        self.is_connected = True
    

    Adding that to your dispatcher will give you a way to check if the socket is connected or not, thanks to some stack trace (python -m trace -t script.py) in Python I managed to figure out that the asyncore class automaticly created that function for whatever reason, and it was called continiously as long as the socket was connected or in a connected state.

    After that, i also replaced the threaded asyncore.loop() and replaced it with a "static" placement locking your main thread, one of these two combinations (or both) solved the issue for now.. the logic isn't the same as in my problem which i don't like but i assume that i'll be needing to create my own dispach_event just like if i were to do a OpenGL GUI class where i would call dispatch_event() manually every loop some how in the thread to "keep things alive".. it's just a thought..

    Anyway, here's a working example:

    #!/usr/bin/python
    # -*- coding: iso-8859-15 -*-
    import asyncore, socket
    from threading import *
    from time import sleep
    from os import _exit
    from logger import *
    from config import *
    
    def _map():
        return {}
    def _array():
        return []
    
    class logDispatcher(Thread, asyncore.dispatcher):
        def __init__(self, config=None):
            self.inbuffer = ''
            self.buffer = ''
            self.lockedbuffer = False
            self.is_writable = False
    
            self.is_connected = False
    
            self.exit = False
            self.initated = False
    
            asyncore.dispatcher.__init__(self)
            Thread.__init__(self)
    
            self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
            try:
                self.connect((server, server_port))
            except:
                log('Could not connect to ' + server, 'LOG_SOCK')
                return None
    
            self.start()
    
        def handle_connect_event(self):
            self.is_connected = True
    
        def handle_connect(self):
            self.is_connected = True
            log('Connected to ' + str(server), 'LOG_SOCK')
    
        def handle_close(self):
            self.is_connected = False
            self.close()
    
        def handle_read(self):
            data = self.recv(8192)
            while self.lockedbuffer:
                sleep(0.01)
    
            self.inbuffer += data
    
    
        def handle_write(self):
            while self.is_writable:
                sent = self.send(self.buffer)
                sleep(1)
    
                self.buffer = self.buffer[sent:]
                if len(self.buffer) <= 0:
                    self.is_writable = False
                sleep(0.01)
    
        def _send(self, what):
            self.buffer += what + '\r\n'
            self.is_writable = True
    
        def run(self):
            sleep(1)
            log('Log engine initating (hooking on to main)', 'LOG_CORE')
    
            main = None
            for t in enumerate():
                if t.getName() == 'MainThread':
                    main = t
    
            log('Log engine attached to main', 'LOG_CORE')
    
            while (main and main.isAlive()) and (self.connected or self.is_connected):
                print 'WHAM', self.connected, self.is_connected
                sleep(1)
    
    while 1:
        logDisp = logDispatcher()
        asyncore.loop(0.1)
        log('Logserver disconnected, trying to reconnect!', 'CORE')
        sleep(10)