【问题标题】:Python TCP Server using select()使用 select() 的 Python TCP 服务器
【发布时间】:2018-04-26 02:38:38
【问题描述】:

这是我的第一个条目@stackoverflow;-))

我需要一个 Python3 TCP 服务器,它将客户端的所有输入发送给其他参与者。服务器工作,但不幸的是消息只返回给发送客户端。一旦第二个客户端发送内容,它就会获取所有条目。因此,这些条目在输出队列中可用。

为什么 select() 不能识别条目?

感谢支持。

`

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)

处理输入

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]

处理输出

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)

处理“异常情况”

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]

`

【问题讨论】:

    标签: python python-3.x sockets select tcpserver


    【解决方案1】:

    您的问题是,当您从 output 列表中读取某些内容时,您只会将其添加到列表中。相反,您应该在将某些内容写入其消息队列时执行此操作。

    接收部分应该变成:

            ...
            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:
                ...
    

    根据您自己的要求,您应该只为其他参与者排队消息:

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

    最后,您经常测试outputs 中是否存在套接字。这让我们认为setlist 更合适。

    【讨论】:

    • 就是这样!谢谢谢尔盖!
    • @MartinH:不客气。如果有帮助,您能否接受答案(复选标记)以告诉未来的读者这个问题有解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-20
    • 2017-12-23
    • 1970-01-01
    • 2013-04-11
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    相关资源
    最近更新 更多