簡體   English   中英

Python似乎隨機關閉套接字

[英]Python closing sockets at random it seems

我一直在尋找和處理這個問題一個星期。 我有客戶端代碼,導致select()返回實際上由於外部原因而關閉的套接字,並拋出錯誤9錯誤的文件描述符,但是我測試了來自其他python文件的代碼,無法將其出錯。 我已經嘗試了一百萬件事情。 這是服務器端的一段代碼:

注意:這將工作幾次迭代,然后突然中斷,由於文件描述符甚至在消息/無消息都存在該套接字的鍵的情況下中斷,因此它在message_queue中作為關鍵錯誤而出錯。

#Create the socket to communicate with uWSGI applications
server_address = ('localhost', 10001)
server = create_server_socket(server_address)
#Sockets which we expect to read on from select()
input_sockets = [server]
#Sockets which we expect to write to from select()
output_sockets = []
#Message buffer dicitonary for outgoing messages
message_queue = {}
#Now wait for connections endlessly
while input_sockets:
    print >> sys.stderr, "Waiting for the next event..."
    readable, writable, exceptional = select.select(input_sockets, output_sockets, input_sockets)
    #Handle input_sockets
    for s in readable:
        #Server socket is available for reading now
        if s is server:
            #Create a connection and address object when incoming request is recieved
            connection, client_addr = s.accept()
            print >> sys.stderr, "Connection recieved from %s!" % (client_addr,)
            #Set client connection to non blocking as well
            connection.setblocking(0)
            #Add this socket to input sockets as it will read for client data
            input_sockets.append(connection)
            #Give connection a queue for sending messages to it
            message_queue[connection] = Queue.Queue()
        #A client has sent data so we can handle its request
        else:
            #Pull data from the client
            data = ""
            try:
                while True:
                    message = s.recv(1024)
                    if not message:
                        break
                    data += message
            except Exception as e:
                print str(e)
            if data:
                #Readable client socket has data
                print >> sys.stderr, 'Recieved "%s" from %s' % (data, s.getpeername())
                message_queue[s].put(data)

                #Add output channel now to send message
                if s not in output_sockets:
                    output_sockets.append(s)
            #There is no data to be read, socket must be closed
            else:
                print >> sys.stderr, 'Closing', client_addr,'after recieving no data.'
                #Stop listening for input on the socket
                if s in output_sockets:
                    output_sockets.remove(s)
                input_sockets.remove(s)
                #Close the connection
                s.close()
                del message_queue[s]
    #Handle writable connections    
    for s in writable:
        if s:
            try:
                next_message = message_queue[s].get_nowait()
            except:
                print >> sys.stderr, 'No data to send for', s.getpeername()
                output_sockets.remove(s)
            else:
                try:
                    print >> sys.stderr, 'Sending "%s" to %s' % (next_message, s.getpeername())
                    s.sendall(next_message)
                except:
                    print >> sys.stderr, 'No data to send for', s.getpeername()
                    output_sockets.remove(s)
                #s.sendall('EOF:!@#$:EOF')
    #Now handle any exceptions
    for s in exceptional:
        print >> sys.stderr, 'Handling exception on ', s.getpeername()
        input_sockets.remove(s)
        if s in output_sockets:
            output_sockets.remove(s)
        s.close()
        #Remove any messages
        del message_queue[s]

客戶:

messages = [ 'This is the message. ',
         'It will be sent ',
         'in parts.',
         ]
server_address = ('localhost', 10001)

# Create a TCP/IP socket
socks = [ socket.socket(socket.AF_INET, socket.SOCK_STREAM),
          socket.socket(socket.AF_INET, socket.SOCK_STREAM),
          ]

# Connect the socket to the port where the server is listening
print >>sys.stderr, 'connecting to %s port %s' % server_address
for s in socks:
    s.connect(server_address)
for message in messages:

    # Send messages on both sockets
    for s in socks:
        print >>sys.stderr, '%s: sending "%s"' % (s.getsockname(), message)
        s.send(message)

    # Read responses on both sockets
    for s in socks:
        data = s.recv(1024)
        print >>sys.stderr, '%s: received "%s"' % (s.getsockname(), data)
        if not data:
            print >>sys.stderr, 'closing socket', s.getsockname()
            s.close()

注意:此客戶端僅用於測試並開始傳遞消息。

當套接字以可讀和可寫方式返回並且關閉套接字時,代碼中會出現爭用,因為讀取返回了0個字節。 在這種情況下,您可以從input_socketsoutput_socketsmessage_queue刪除套接字,但是關閉的套接字仍然是writable ,因此它將嘗試在select循環的同一迭代中writable該套接字。

我不知道這是否是一場比賽,因為您既沒有顯示調試輸出,也沒有說過在EBADF上遇到的困難。 為了追蹤類似的問題,我建議您在代碼中添加更多調試信息,以了解關閉套接字的位置以及嘗試處理套接字的位置,因為該套接字可讀或可寫,以便您在查看套接字時能真正找到比賽的確切位置。調試輸出。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM