首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >boost.asio :多端口应用层协议

boost.asio :多端口应用层协议
EN

Stack Overflow用户
提问于 2014-04-02 18:00:37
回答 1查看 788关注 0票数 1

我正在设计一个客户端服务器应用程序,我需要在它们之间使用三个不同的通道。在模式的下面,客户机打开到服务器(1)的连接,然后服务器在其他端口(2)上打开到客户机的两个连接。

代码语言:javascript
复制
|-----------|                  |-----------|
|           |  (1) port: 8000  |           |
|           |<-----------------|           |
|           |                  |           |
|           |                  |           |
|  Server   |  (2) port: 8001  |  Client   |
|           |----------------->|           |
|           |                  |           |
|           |  (2) port: 8002  |           |
|           |----------------->|           |
|-----------|                  |-----------|

一个简单的通道服务器示例:server.cpp

我的问题是如何在boost.asio框架的基础上实现这一点?或者,如何从服务器打开新的连接(2)?

也许一个更好的协议是在建立第一个连接时打开来自客户端的另外两个连接?但是在这种情况下,asio所使用的结构是什么呢?

提前谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-04-03 00:51:12

正如已经指出的,任何需要健壮的系统都不应该假定路由/防火墙是可以从服务器返回到客户端的连接。

我们怎么解决这个问题?

  • 客户端连接服务器:8000
  • 服务器使用会话UID进行响应。
  • 客户端负责连接另外两个“通道”,使用会话UID作为相关ID。
  • 服务器决定,如果与给定会话UID参与的所有3个“通道”(即套接字)都已连接,则会话将完全就绪。如果出现超时,服务器将记录整个会话并关闭任何已打开的套接字。

这很容易,但需要有线协议来协调会话和连接的“角色”。我最初选择不把它作为一个演示来实现。相反,我认为这将是一个很好的练习,学习Boost Asio,并实现回通道(从服务器端启动),如您的原始绘图。

完整的代码在github:https://gist.github.com/sehe/9946161

备注:

  • 有一个“通用”监听器实现,用于服务器(端口8000)和“回通道”(端口881,8002)。请参阅listener.hpp
  • 我选择了无堆栈的协同线方法。这需要增强Asio 1.54
  • 这种方法导致了shared_ptr<>的相对滥用,至少在我看来是这样。原因是,如果coroutine (也是完成函子)是可以复制的,没有任何问题,这是非常有益的。我可能可以通过使类本身为enable_shared_from_this并绑定到shared_from_this来清理这个问题。现在的好处是(几乎)没有bind-expressions。
  • 在服务器类on_accept中创建“回通道”: 虚拟bool on_accept(tcp::套接字&套接字)覆盖{ auto = socket.remote_endpoint().address().to_string();//,目前设置备份连接都是同步的- //,在实践中可能不能很好地工作(缩放、延迟),但是.尝试{ tcp::resolver解析器(socket.get_io_service());自动ep1 =resolver.resolve(tcp::resolver::query(主机,"8001"));自动ep2 =resolver.resolve(tcp::resolver::query(主机,"8002"));backsock1 = make_shared(socket.get_io_service());backsock2 =resolver.resolvebacksock2 1->connect(*ep1);backsock2 2->connect(*ep2);std::cerr << "on_accept:反向连接“”<< host <<“\n;} catch(std::exception const& e) { std::cerr << "on_accept:‘<< e.what() << '”表示“<< host <<”\n;返回false;}返回base_type::on_accept(套接字);}
  • 如果on_accept失败(例如,对于我们的服务器无法连接回通道),将在“主”套接字(初始连接)上返回错误,并中止会话。

有三个方案:

  • run_server (监听端口8000)
  • run_client (连接到端口8000,监听881,8002),并发送1条消息。您可以通过在反向通道上连接并在所有三个套接字上发送不同的消息来观察服务器的响应。
  • test (将两者结合在一起): #include #include #include "client.hpp“int main() { boost::asio::io_service svc;// start service在单独的线程boost上::boost::asio::io_service{svc.post(演示:服务器(Svc));svc.run();};boost::this_thread::sleep_for(boost::chrono::milliseconds(500));//允许服务器开始接受// post客户端通信到服务std::cerr <<“启动发送消息的测试客户端.\n”;演示:客户端(svc,"localhost","8000");//等待中断(或新连接) th.join();}

最后一个程序的输出如下:

代码语言:javascript
复制
Starting a test client that sends a message...
on_accept: back channels connected for 127.0.0.1
listener 127.0.0.1:8000: accepting connection from 127.0.0.1:40999
listener 127.0.0.1:8000: 'hello world from demo client' received from 127.0.0.1:40999
listener 127.0.0.1:8001: accepting connection from 127.0.0.1:40132
listener 127.0.0.1:8002: accepting connection from 127.0.0.1:37970
listener 127.0.0.1:8001: 'We've received a request of length 29' received from 127.0.0.1:40132
listener 127.0.0.1:8002: 'We're handling it in void demo::server::do_back_chatter(const string&)' received from 127.0.0.1:37970
listener 127.0.0.1:40999: 'ECHO hello world from demo client' received from 127.0.0.1:8000
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22819395

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档