Python TCP Server using select()

三世轮回 提交于 2019-12-24 07:49:46

问题


this is my first entry @stackoverflow;-))

I need a Python3 TCP server, which sends all inputs of the clients to the other participants. The server works, but unfortunately the message is only returned to the sending client. As soon as the second client sends something, it gets all entries.The entries are therefore available in the output queue.

Why are the entries not recognized by select ()?

Thx for the support.

`

import select
import socket
import sys
import queue

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setblocking(0)

server_address = ('192.168.100.28', 8888)
print ("starting up on %s port %s" % server_address)
server.bind(server_address)

server.listen(5)

inputs = [ server ]
outputs = [ ]
message_queues = {}




while inputs:
    print ("\nwaiting for the next event")
    readable, writable, exceptional = select.select(inputs, outputs, inputs)

Handle inputs

for s in readable:

    if s is server:
        # A "readable" server socket is ready to accept a connection
        connection, client_address = s.accept()
        print ("new connection from", client_address)
        connection.setblocking(0)
        inputs.append(connection)

        # Give the connection a queue for data we want to send
        message_queues[connection] = queue.Queue()
    else:
        data = s.recv(1024)
        if data:
            # A readable client socket has data
            print ('received "%s" from %s' % (data, s.getpeername()))
            # Add output channel for response
            #message_queues[s].put(data)
            if s not in outputs:
                outputs.append(s)
            for aQueue in message_queues:
                message_queues[aQueue].put(data)
                # AQueue.send ("Test".encode())
        else:
            # Interpret empty result as closed connection
            print ("closing", client_address, "after reading no data")
            # Stop listening for input on the connection
            if s in outputs:
                outputs.remove(s)
            inputs.remove(s)
            s.close()

            # Remove message queue
            del message_queues[s]

Handle outputs

for s in writable:
    try:
        next_msg = message_queues[s].get_nowait()
    except queue.Empty:
        # No messages waiting so stop checking for writability.
        print ("output queue for", s.getpeername(), "is empty")
        outputs.remove(s)
    else:
        print ('sending "%s" to %s' % (next_msg, s.getpeername()))
        s.send(next_msg)

Handle "exceptional conditions"

for s in exceptional:
    print ("handling exceptional condition for", s.getpeername())
    # Stop listening for input on the connection
    inputs.remove(s)
    if s in outputs:
        outputs.remove(s)
    s.close()

    # Remove message queue
    del message_queues[s]

`


回答1:


Your problem is that you only add a peer to the output list when you read something from it. You should instead do it when you write somthing to its message queue.

The receiving part should become:

        ...
        data = s.recv(1024)
        if data:
            # A readable client socket has data
            print ('received "%s" from %s' % (data, s.getpeername()))
            # Add output channel for response
            #message_queues[s].put(data)
            # if s not in outputs:
            #    outputs.append(s)
            for aQueue in message_queues:
                message_queues[aQueue].put(data)
                if aQueue not in outputs:       # enqueue the msg
                    outputs.append(aQueue)      # and ask select to warn when it can be sent
                # AQueue.send ("Test".encode())
        else:
            ...

According to your own requirements, you should only enqueue messages for other participants:

            for aQueue in message_queues:
                if aQueue != s:      # only send to other participants
                    ...

Finally, you often test existence of a socket in outputs. That let think that a set would be more appropriate than a list.



来源:https://stackoverflow.com/questions/47263904/python-tcp-server-using-select

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!