0

我使用 websocketpp 库设置了一个简单的广播服务器,用于个人 HTML + Javascript 聊天。到目前为止,一切都很完美,只有一个例外。此聊天仅供两个人同时使用。如果第三个人试图进来,他或她必须关上门。所以,逻辑是:

1 -> 服务器正在监听。

2 -> 爱丽丝连接。

3 -> Bob 连接。

4 -> 服务器停止监听。向 Alice + Bob 广播。

5 -> Carlos 尝试连接,但端口已关闭。

6 -> Bob 断开连接。

7 -> 卡洛斯连接。

8 -> 服务器停止监听。向 Alice + Carlos 广播。

起初我认为这会很简单,但在许多错误和阅读之后,我只是卡住了。我可以让我的服务器在握手过程之后停止监听,但是在此之后message_handler服务器端停止工作并且我无法从客户端收到任何消息,即使客户端仍然完全连接。我知道set_validate_handler并且我已经设置为同时只允许两个连接,但是服务器仍然在监听。我需要的是一种让服务器停止监听端口的方法。

我正在尝试关闭监听并以这种方式保持已经建立的连接:

void on_open( connection_hdl hdl )
{
    // Insert
    m_connections.insert( hdl );

    // Stop listening
    m_server.stop_listening();
}

但是,它给了我以下输出:

[2015-07-12 17:06:47] [connect] WebSocket Connection [::1]:58589 v13 "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36" / 101
[2015-07-12 17:06:47] [fail] WebSocket Connection Unknown - "" - 0 websocketpp:26 Operation canceled[2015-07-12 17:06:47] [info] Error getting remote endpoint: system:10009 (The file handle supplied is not valid)
[2015-07-12 17:06:47] [info] asio async_shutdown error: system:10009 (The file handle supplied is not valid)
remote_endpoint: The file handle supplied is not valid

客户端甚至无法连接。否则,如果我m_server.stop_listening();在建立连接后使用 ,客户端仍保持完美连接,但服务器停止接收其消息,或者至少我无法在void on_message( connection_hdl hdl, server::message_ptr msg ).

4

1 回答 1

0

虽然我建议重新考虑聊天应用程序的设计(也许每个人都有两个参与者的聊天室比两个连接的整个应用程序更好?),我认为你可以编写一个简单的“肮脏”解决方案......

...为什么没有一个“全局”计数器,如果数量太高就直接拒绝连接?

如果从您的代码中借用,也许它看起来像这样(我不知道这是否有效,这只是一个大纲):

int connections_count = 0
void on_open( connection_hdl hdl )
{
    connections_count += 1
    if(connections_count >= 2) { return connection_hdl.close}
    // Insert
    m_connections.insert( hdl );
}
void on_close ( connection_hdl hdl )
{
    connections_count -= 1
}

因为我的 C++ 编码很烂,所以我将使用Plezi 框架在 Ruby 中编写一个快速的服务器示例……将其视为可以在其中运行的伪代码irb(Ruby 的终端解释器):

require 'plezi'

class ChatCtrl
   def pre_connect
      return self.class.add_client
   end

   def on_message data
     broadcast :_post_data, data
   end

   def on_disconnect
      self.class.remove_client
   end

   def _post_data data
     response << data
   end

   # these are class methods, designated by adding `self.` to the name
   # they hold the global number of connected clients.
   # they also handle the multi-threading security, because Plezi is multi-threaded.

   def self.add_client
      @locker ||= Mutex.new # multi-thread security
      @clients ||= 0
      return false if @clients >= 2
      @locker.synchronize { @clients += 1 }
   end
   def self.remove_client
      @locker.synchronize { @clients -= 1 }
   end
end

listen

route '*', ChatCtrl

exit

我添加了一些多线程安全性,但如果您的应用程序是单线程的,这可能不是必需的。

这很丑陋,但它应该工作。

祝你好运!

于 2015-07-12T21:41:29.957 回答