简体   繁体   中英

Python unix socket server recieves same data from client multiple times

I am trying to communicate between ruby and python through unix sockets, and i need multithreaded python server to respond to many ruby clients. All work fine except 1 thing, that i send message from client only once, but the server recieves it 2 times somehow.

What maybe the problem?

Here's my python server code:

import socket
import os
import threading
import time
import logging

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

# create a file handler
handler = logging.FileHandler('python_server.log')
handler.setLevel(logging.DEBUG)

# create a logging format
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)

# add the handlers to the logger
logger.addHandler(handler)

class ThreadedServer(object):

    def __init__(self, socket_path):
        if os.path.exists(socket_path):
            os.remove(socket_path)

        logger.info("Opening socket...")
        self.server = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
        self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server.bind(socket_path)

    def listen(self):
        size = 1024
        logger.info("Listening...")
        try:
            while True:
                datagram, address = self.server.recvfrom(1024)
                threading.Thread(target = self.listenToClient,args = (self.server, datagram, address, logger)).start()
        finally:
            logger.info("Shutting down...")
            self.server.close()
            os.remove("/tmp/python_socket_server")
            logger.info("Done")

    def listenToClient(self, server, datagram, address, logger_obj):
        while True:
            try:
                if datagram:
                    logger_obj.info('Recieved message from client %s', address)
                    time.sleep(5)
                    server.sendto(bytes("I hear you buddy", 'UTF-8'), address)
                    logger_obj.info('Responded to client %s', address)
                else:
                    raise ValueError('Client disconnected')
            except:
                return False

if __name__ == "__main__":
    socket_path = "/tmp/python_socket_server"
    ThreadedServer(socket_path).listen()

My ruby client:

require "socket"

SERVER_SOCKET = "/tmp/python_socket_server"

threads = []

5.times do 
    threads << Thread.new do 
        socket = Socket.new :UNIX, :DGRAM
        socket.bind Socket.pack_sockaddr_un("")

        socket.send("Hello server, can you hear me?\n", 0, Socket.pack_sockaddr_un(SERVER_SOCKET))
        puts socket.recvfrom(1024)

        socket.close
    end
end

threads.each { |thr| thr.join }

And the log looks like this:

2018-03-05 22:08:43,566 - __main__ - INFO - Opening socket...
2018-03-05 22:08:43,567 - __main__ - INFO - Listening...
2018-03-05 22:08:45,572 - __main__ - INFO - Recieved message from client b'\x00025c0'
2018-03-05 22:08:45,573 - __main__ - INFO - Recieved message from client b'\x00025c1'
2018-03-05 22:08:45,573 - __main__ - INFO - Recieved message from client b'\x00025c2'
2018-03-05 22:08:45,574 - __main__ - INFO - Recieved message from client b'\x00025c3'
2018-03-05 22:08:45,574 - __main__ - INFO - Recieved message from client b'\x00025c4'
2018-03-05 22:08:50,574 - __main__ - INFO - Responded to client b'\x00025c3'
2018-03-05 22:08:50,575 - __main__ - INFO - Recieved message from client b'\x00025c3'
2018-03-05 22:08:50,577 - __main__ - INFO - Responded to client b'\x00025c1'
2018-03-05 22:08:50,577 - __main__ - INFO - Recieved message from client b'\x00025c1'
2018-03-05 22:08:50,577 - __main__ - INFO - Responded to client b'\x00025c2'
2018-03-05 22:08:50,577 - __main__ - INFO - Recieved message from client b'\x00025c2'
2018-03-05 22:08:50,578 - __main__ - INFO - Responded to client b'\x00025c0'
2018-03-05 22:08:50,578 - __main__ - INFO - Recieved message from client b'\x00025c0'
2018-03-05 22:08:50,579 - __main__ - INFO - Responded to client b'\x00025c4'
2018-03-05 22:08:50,579 - __main__ - INFO - Recieved message from client b'\x00025c4'
2018-03-05 22:08:56,437 - __main__ - INFO - Shutting down...
2018-03-05 22:08:56,438 - __main__ - INFO - Done

The problem is with the while True: at the start of your listenToClient method. (If you just remove that line, it should work as you expect it to.)

You get a datagram already in listen , so your listenToClient only needs to handle it and return data to the other end. (In that way, it should probably be called handleClientRequest or respondToClient or similar, that might be more appropriate.)

With the while True: in place, it's going back to the start of that loop, where datagram is still set to the same value, so it's trying to reply to the other side once again. (Those threads probably get stuck there, since the other side stopped receiving.)

I hope that helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM