Python socket keeps open even using Close

Asked

Viewed 584 times

1

I have a Python App that uses Socket, this App runs on XBMC’s Kodi, and when I close the App I would like to close the Socket and take down customers, the problem is that even I using shutdown(socket.SHUT_RDWR) and close() in the client the Socket is open occupying the port, the Socket is only closed if the client also closes the connection. In all languages I have worked with Socket (C++, Java, PHP and Swift), if the Host closes the connection everyone falls. But in Python it’s different, I wonder what I have to do to kill the connection. Python script:

import sys
import socket
import xbmcgui
import xbmc
import thread
import json

class GUI(xbmcgui.WindowXML):

    def onInit(self):
        # start socket server
        self.running = True
        xbmc.log("Inciando server")

        # thread client users
        self.users = [];

        # get exit ids
        self.action_exitkeys_id = [10, 13]

        # get control ids
        self.texto = 30
        self.conteudo = 31
        self.logo = 32
        self.erro = 33
        # get control instance
        self.texto_label = self.getControl(self.texto)
        self.conteudo_label = self.getControl(self.conteudo)
        self.logo_img = self.getControl(self.logo)
        self.erro_img = self.getControl(self.erro)

        self.texto_label.setLabel("")
        self.conteudo_label.setLabel("")
        self.logo_img.setVisible(True)
        self.erro_img.setVisible(False)

        try:
           thread.start_new_thread( self.server_listerner, () )
        except:
           xbmc.log( "Error: unable to start thread" )

    def onAction(self, action):
        xbmc.log(str(action.getId()))
        if action.getId() == 10 :
            xbmc.log("Tentando fechar conexao");
            self.running = False
            for user in self.users : 
                xbmc.log("Matando Cliente");
                user.shutdown(socket.SHUT_RDWR);
                user.close();
                del user
                del self.users
            try :
                tmp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                tmp.connect( self.server_address )
                tmp.close();
                del tmp
            except :
                xbmc.log("Conexao ja fechada!")
            self.close()

    def parseJson(self, json_string):
        xbmc.log(json_string)
        data = json.loads(json_string)
        if data["command"]  ==  "setText" :
            self.logo_img.setVisible(False)
            self.texto_label.setLabel(data["param1"])
            self.conteudo_label.setLabel(data["param2"])

        if data["command"] == "clean" :
            self.logo_img.setVisible(True)
            self.texto_label.setLabel("")
            self.conteudo_label.setLabel("")

        if data["command"] == "play" :
            xbmc.Player().pause()

        if data["command"] == "pause" :
            xbmc.Player().pause()

    def server_listerner(self):
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server_address = ('localhost', 9191)
        try:
            self.sock.bind(self.server_address)
        except Exception, e:
            self.erro_img.setVisible(True)
            return



        self.sock.listen(1)
        while self.running:
            # Wait for a connection
            connection, client_address = self.sock.accept()
            self.users.append(connection);
            try:
                #xbmc.log( 'connection from ' + client_address )

                # Receive the data in small chunks and retransmit it
                while True:
                    data = connection.recv(4096)
                    #xbmc.log( 'received "%s"' % data )
                    if data:
                        #xbmc.log( 'sending data back to the client' )
                        self.parseJson(data)
                    else:
                        xbmc.log( 'no more data from' )
                        break
            except:        
                xbmc.log("Cliente deu pau")
                connection.shutdown(socket.SHUT_RDWR);
                connection.close()
                del connection
                continue;
            xbmc.log("Matando cliente")
            #connection.shutdown(socket.SHUT_RDWR);
            connection.close()
            del connection

        xbmc.log("fechando conexao");
        self.sock.shutdown(socket.SHUT_RDWR);
        self.sock.close()   

        del self.sock

2 answers

2


Generic response: the client has to do its part, when the result of the recv in client for 0 this means that the server will no longer respond, so it is the responsibility of the client to do the close, otherwise the socket will remain open.

You can see this situation in the client with netstat, where normally appears ESTABLISHED will probably appear CLOSE_WAIT. No server will appear CLOSING.

In short: is client problem.

0

To documentation do Python diz: "close() releases the Resource Associated with a Connection but does not necessarily close the Connection immediately. If you want to close the Connection in a Timely fashion, call shutdown() before close()." - that is, use the method shutdown before the close.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.