c++中的跨平台网络代码

Cross-Platform Networking Code in C++?

本文关键字:网络 代码 跨平台 c++      更新时间:2023-10-16

我正在开发一个新的应用程序,虽然我的背景主要是基于Mac/iOS,但我需要开发一个Windows应用程序来参加他们的创新杯。

这个项目包括通过套接字连接(到服务器,而不是ad-hoc)客户端之间的通信,我需要Mac和Windows客户端能够相互通信。我还希望不必编写两次网络代码,只需在两个平台上编写不同的本机ui代码。这使得网络更容易(我相信两个不同的平台不会以不同的方式与服务器交互),并允许在两个平台上使用本机UI。

c++是这个任务的最佳语言吗?两个平台上的标准库相同吗?我知道我将不得不使用微软的Visual c++库,因为从c#中使用c++代码似乎很难;这是真的吗?

我以前从来没有真正写过跨平台的应用程序,尤其是处理平台间网络的应用程序。

如果你打算使用c++,我强烈建议你看看Boost中的ASIO,这是一个编写一次代码并支持两个平台的好方法。

关于c++是否是合适的语言是相当主观的。我个人的感觉是,如果你需要问,很有可能,这不是最好的方法。

选择c++实现网络代码的原因有:

  • 通过精心设计和实现的代码可以实现非常低的延迟和高吞吐量。
  • 可以显式控制内存管理-避免与垃圾收集相关的性能变化。
  • 可能与其他本机库紧密集成进程中的网络代码。
  • 构建适合在资源受限环境中部署的小型组件的潜力。
  • 对C套接字API的低级访问暴露了诸如套接字选项等功能,以使用超出普通TCP/IP和UDP的协议。

避免使用c++的原因如下:

  • 与高级语言(如Java/c#/Python等)相比,开发代码的效率较低
  • 更有可能出现重大的实现错误(指针滥用等)
  • 需要在每个平台上验证代码编译。

您可能考虑的替代方案包括:

  • Python……直接使用低级套接字支持或高级Twisted库。使用方便的高级习惯用法和最少的移植工作进行快速开发。最大的缺点-对高吞吐量系统的多处理器内核支持不足。
  • Ruby(插座)/Perl (IO::套接字)…高级语言,如果通信信息以文本字符串表示,则可能特别适合。
  • Java……垃圾收集简化了内存管理;广泛的现有库。
  • CLR语言(c#等)也像Java一样被垃圾收集…WCF是一个有效的框架,可以在其中开发定制协议……这可能是有用的。

你还问:"我知道我将不得不使用微软的Visual c++库,因为似乎很难从c#中利用c++代码;这是真的吗? "

你可以完全避免Visual c++库——要么使用c++以外的语言开发,要么使用替代的c++编译器——例如Cygwin或MinGW提供的c++…尽管我建议使用Visual c++来为Windows构建C和c++代码。

从c#中使用c++代码并不难——尽管我不推荐这样做。这可能过于复杂了。Visual c++可以(可选地)从c++源代码编译"托管代码"(有一些语法扩展需要掌握,使用Mono和Visual c++的互操作语法略有不同,但我认为这些都不是主要问题)。这些CLR对象直接与c#对象交互,并且可以毫无问题地链接到一个程序集中。使用Pinvoke也很容易访问本机dll(可能使用c++为本机体系结构编写)。然而,所有这些都是无关紧要的,因为。net框架对system.net中的低级网络(类似于Winsock[2]所提供的)有很好的支持——这为类似的功能提供了一个方便的面向c#的接口,并且可能会提供一个更方便的API来使用c#(或VB)进行开发。

我建议你看看Qt,在我看来Qt是做跨平台应用最好的c++库之一。与Boost相比,Qt的好处是Qt有甚至GUI类。

最佳语言是非常主观的,但如果您想要具有有用抽象和C风格语法的可移植快速代码,c++是一个不错的选择。注意,如果你对c++一窍不通,那么你的学习曲线会很陡峭。

由ISO标准定义的库根据定义在每个平台上都是相同的,但是它的实现可能更少或更兼容。也就是说,gcc、clang和MSVC(post .net)都很好地实现了c++ 98。只要你不使用编译器特定的扩展名。

我强烈建议查看boost asio(以及boost库)用于您的网络,它使用非常高效的proactor设计模式。然而,你确实需要一些时间来理解它。

http://www.boost.org/doc/libs/1_48_0/doc/html/boost_asio.html

坚持使用标准库和boost,在大多数情况下,跨平台问题不是主要问题。

最后,我会避免使用c++ 11的特性来编写跨平台代码,因为MSVC、GCC和Clang都实现了该标准的不同部分。

如果你想花一年时间,投入1000小时,一定要使用boost::asio。或者您可以使用围绕boost::asio构建的库来调用c++网络模板。这是一个跨平台的网络,你可以在这里找到它:https://bitbucket.org/ptroen/crossplatformnetwork/src/master/

它可以在Windows,Android, Macos和Linux上编译。

这并不是说如果你在boost::asio方面达到绝对的专家水平,你可以在性能上做得更好一点,但是如果你想获得98%的性能提升,你可能会发现它很有用。它还支持HTTP,HTTPS,NACK,RTP,TCP,UDP,MulticastServer和多播客户端。

例子:TCPServer: https://bitbucket.org/ptroen/crossplatformnetwork/src/master/OSI/Application/Stub/TCPServer/main.ccHTTPServer: https://bitbucket.org/ptroen/crossplatformnetwork/src/master/OSI/Application/Stub/HTTPServer/httpserver.cc

OSI::Transport::TCP::TCP_ClientTransport<SampleProtocol::IncomingPayload<OSI::Transport::Interface::IClientTransportInitializationParameters>, SampleProtocol::OutgoingPayload<OSI::Transport::Interface::IClientTransportInitializationParameters>, 
    SampleProtocol::SampleProtocolClientSession<OSI::Transport::Interface::IClientTransportInitializationParameters>, OSI::Transport::Interface::IClientTransportInitializationParameters> tcpTransport(init_parameters);;
SampleProtocol::IncomingPayload< OSI::Transport::Interface::IClientTransportInitializationParameters> request(init_parameters);
request.msg = init_parameters.initialPayload;
std::string ipMsg=init_parameters.ipAddress;
LOGIT1(ipMsg)
tcpTransport.RunClient(init_parameters.ipAddress, request);

我有偏见,因为我写了这个库。

您还可以检查此通信库:finalmq

该库具有以下属性:c++,跨平台,异步/非阻塞,多种协议(TCP, HTTP, mqtt5),多种编码格式(json, protobuf)。查看示例