【问题标题】:select() issue with a push server - c/c++推送服务器的 select() 问题 - c/c++
【发布时间】:2014-08-06 02:33:06
【问题描述】:

我正在用 C++ 为 Windows 和 Unix 系统编写服务器。

此服务器的一个关键特性是它必须能够随时接收和发送网络数据包。 具体来说,服务器必须能够向客户端发送数据,不仅要响应他们的消息,还要能够在推送中异步向他们发送数据包。

我在实施在上述场景中使用select() 函数的解决方案时遇到了困难。 我目前实施的解决方案根本无法说服我,我认为它可以用更好的模式/解决方案来实施。

我目前有一个专用线程(选择器),它通过侦听读取服务器套接字(接受新连接)和连接到服务器的套接字的事件来执行选择。

这是主 select() 循环:

    if((sel_res_ = select(nfds_+1, &read_FDs_, NULL, &excep_FDs_, &sel_timeout)) > 0){
    if(FD_ISSET(serv_socket, &read_FDs_)){
        //we have to handle a newly connection.
        ...
        if(sel_res_ > 1){
            //in addition to the newly connection, there is also some other message incoming on client sockets.
            ...
        }
    }else{
        //we have to handle incoming messages on client sockets
        ...
    }
}

此解决方案适用于接收数据并以同步形式响应客户端请求。 但是,服务器还必须能够发送异步数据,并在必要时发送推送数据包。

为此,我目前使用单独的线程直接在客户端套接字上执行send()

这个方案说服不了我,我想把数据包的接收和发送集中在选择器线程上。

主要困难在于select() 本质上是阻塞的,在客户端不发送任何数据包或触发超时之前我无法控制。 将超时设置得很低的解决方案并不能说服我;我认为这是一个简单的解决方案,实际上是在进行主动等待,而且不仅是在最坏的情况下,我会在发送推送数据包之前付出超时的代价。

我想到了一个更“优雅”的解决方案;我认为,会很好用,但只适用于 Unix/Linux 平台。 我想使用匿名管道并将匿名管道读取描述符插入select() read_FDs_。 这样,当一个线程想要在 push 中发送数据时,它会在此管道上写入一些内容,中断select() 并将控制权返回给选择器,然后选择器可以倾向于将数据发送到客户端,而不会浪费大量时间. 不幸的是,我认为该解决方案无法在 Windows 上实现,因为该系统上的 select() 函数仅适用于实际上是套接字的 fd。

所以问题是:是否有一些众所周知的解决方案可用于解决这种情况(Linux 和 Windows)?

【问题讨论】:

  • 使用两个线程,一个读一个写。

标签: c windows unix select


【解决方案1】:

您可以创建一个自连接的 UDP 套接字,这在 Windows 和 Linux 上同样适用。

基本上,您创建一个 UDP 套接字,bind()INADDR_LOOPBACK 和端口 0,connect() 到它自己(地址取自 getsockname())。

此时,您可以向自己发送一条单字节消息(或更具体的消息)来唤醒自己。

【讨论】:

    猜你喜欢
    • 2010-11-06
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 2014-09-09
    • 1970-01-01
    • 2013-11-24
    • 1970-01-01
    相关资源
    最近更新 更多