Socket Python keeps open even using Close

1

I have an App in Python that uses Socket, this App runs on Kodi from XBMC, and when I close the App I would like to close the Socket and knock down the clients, the problem is that even I using shutdown(socket.SHUT_RDWR) e close() in the client the Socket is opened occupying the port, the Socket is only closed if the client also close the connection. In all languages I have worked with Socket (C ++, Java, PHP and Swift), if the Host close the connection everyone falls. But in Python it's different, what do 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
    
asked by anonymous 19.09.2016 / 05:01

2 answers

2

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

You can see this situation on the client with netstat, where it usually appears ESTABLISHED will probably appear CLOSE_WAIT. On the server will appear CLOSING.

In short: it's the client's problem.

    
19.09.2016 / 05:12
0

Python's documentation says: "close () releases the resource If you want to close the connection in a timely fashion, call shutdown () before close (). " - that is, use the method shutdown before close .

    
03.01.2017 / 13:33