当前位置: 首页 > 知识库问答 >
问题:

使用选择处理多个请求

许嘉珍
2023-03-14

目前我正在研究聊天服务器/客户端项目。我正在努力使用 select 处理多个请求,我的服务器脚本使用 select 模块,但客户端脚本没有。结果是,当用户输入消息时,其他客户端必须编写自己的消息才能通读对话。我已经在网上搜索了很多示例,但只能找到带有 sys.stdin 的代码片段,这不是我想要的。

我很高兴收到任何指示/解释。

服务器代码:

import socket
import select

server_socket = socket.socket()
server_socket.bind(("0.0.0.0", 2855))
server_socket.listen(1)

open_client_sockets = [] # current clients handler
messages_to_send = [] # future message send handler

def send_waiting_messages(wlist):
    for message in messages_to_send:
        (client_socket, data) = message
        if client_socket in wlist: # if current socket in iteration has reading abilities
            client_socket.send(data)
            messages_to_send.remove(message) # remove from future send handler

def broadcast_message(sock, message):
    for socket in open_client_sockets:
        if socket != server_socket and socket != sock:
            socket.send(message)

while True:
    rlist, wlist, xlist = select.select([server_socket] + open_client_sockets, open_client_sockets, []) # apending reading n writing socket to list

    for current_socket in rlist: # sockets that can be read
        if current_socket is server_socket: # if there is a new client
            (new_socket, address) = server_socket.accept() 
            open_client_sockets.append(new_socket) # clients list
        else:
            data = current_socket.recv(1024)
            if len(data) == 0:
                open_client_sockets.remove(current_socket) # remove user if he quit.
                print "Connection with client closed."
                send_waiting_messages(wlist) # send message to specfic client
            else:
                broadcast_message(current_socket, "\r" + '<' + data + '> ')

    # send_waiting_messages(wlist) # send message to specfic client

server_socket.close()

客户端代码

import socket
import msvcrt

client_socket = socket.socket()
client_socket.connect(("127.0.0.1", 2855))

data = ""
def read_message():
    msg = ""
    while True:
        if msvcrt.kbhit():
            key = msvcrt.getch()
            if key == '\r': # Enter key
                break
            else:
                msg = msg + "" + key

    return msg

while data != "quit":
    data = read_message()
    client_socket.send(data)
    data = client_socket.recv(1024)
    print data
client_socket.close()

共有2个答案

牛景同
2023-03-14

服务器端和客户端都存在阻止您的应用程序真正实时的问题。到目前为止,我注意到以下几个:

>

  • 客户端仅在将一些数据写入套接字后才从服务器连接读取数据。请考虑将要从套接字读取的逻辑放入单独的线程中。

    在服务器中,在向客户端发送挂起的消息之前,遍历select()返回的rlist;只有当客户端发送了消息时,客户端fds才会出现在rlist中。发送消息应该基于可写fds,通过在wlist上迭代来完成。但这还有其他问题。。。

    您始终select()所有客户端fd的可写性,即使没有要写入该客户端的挂起消息。最终结果是,您的select()调用几乎总是立即返回,并且会浪费CPU(这有点违背了select的目的)

    您的所有套接字IO都是在“阻塞”模式下完成的,因此如果您发送的数据超过了内核在远程端的接收缓冲区所能处理的数据(通常大约为10MB),则send()可能会阻塞。

    您最好使用异步框架(例如扭曲)来实现这种类型的应用程序。管理所有缓冲区可能既乏味又具有挑战性,而且这是以前已经完成的工作。

  • 壤驷喜
    2023-03-14

    我的服务器脚本使用select模块,但客户端脚本不使用。

    解决方案是在客户端也使用< code>select。在Windows上,不幸的是< code>select不处理< code>sys.stdin,但是我们可以使用超时参数来轮询键盘。

    import socket
    import select
    import msvcrt
    client_socket = socket.socket()
    client_socket.connect(("localhost", 2855))
    msg = ""
    while True:
        ready = select.select([client_socket], [], [], .1)
        if client_socket in ready[0]:
            data = client_socket.recv(1024)
            print data, ' '*(len(msg)-len(data))
            print msg,
        if msvcrt.kbhit():
            key = msvcrt.getche()
            if key == '\r': # Enter key
                if msg == "quit":
                    break
                client_socket.send(msg)
                msg = ""
                print
            else:
                msg = msg + "" + key
    client_socket.close()
    
     类似资料:
    • 问题内容: 等待(不旋转)直到两个(多处理)队列中的任何一个都可用的最佳方法是什么(两者都驻留在同一系统上)? 问题答案: 似乎还没有一种正式的方式来解决这个问题。或至少不是基于此: http://bugs.python.org/issue3831 您可以尝试类似本文所进行的操作-访问基础管道文件句柄: http://haltcondition.net/?p=2319 然后使用选择。

    • 问题内容: 我的外观很好,似乎无法找出如何在一个jQuery选择器语句中选择与某些类匹配的所有元素,例如: 关于如何实现这一目标的任何想法?唯一的其他选择是 但是我正在使用很多类来执行此操作,因此它需要很多代码。 问题答案: 这应该工作: 您必须在$()的第一个参数中全部添加多个选择器,否则,您将为jQuery提供要在其中搜索的上下文,这不是您想要的。 这与您在CSS中所做的相同。

    • 我正在使用标记为我的搜索框创建一个建议列表,但是我不能从数据列表中选择多个值。当前,我得HTML是:

    • 问题内容: 我的Flask应用程序必须进行大量计算才能获取特定页面。在Flask执行该功能时,其他用户无法访问该网站,因为Flask忙于进行大量计算。 有什么方法可以使我的Flask应用程序接受来自多个用户的请求? 问题答案: 是的,将应用程序部署在其他WSGI服务器上,请参阅Flask部署选项文档。 Flask随附的服务器组件实际上仅用于开发应用程序时;即使可以将其配置为处理并发请求(从Flas

    • 问题内容: 我所拥有的: 我有一个nodejs express服务器获取端点,该端点依次调用其他耗时的API(例如大约2秒)。我已经通过回调调用了此函数,使得res.send作为回调的一部分被触发。res.send对象打包了一个对象,该对象将在执行这些耗时的API调用的结果之后创建。因此,仅当我从API调用中获得全部信息时,才能发送我的res.send。 一些代表性的代码。 我要什么 我希望我的服

    • 表模式如下: 表A的主键[ID1(分区键)id2(分区键)id3(群集键)] 表B主键[ID1(分区键)id2(分区键)状态(聚类键)id3(聚类键)] 那么在卡桑德拉我该怎么解决呢?