ICE 网络库尝试

libdatachannel:轻量高效的C++ WebRTC P2P通信库快速上手指南 WebRTC(Web实时通信)是一套支持浏览器与原生应用之间进行点对点(P2P)音视频和数据传输的开放标准协议栈。其核心原理在于通过ICE(交互式连接建立)框架实现NAT穿透,并利用DTLS(数据报传输层安全)和SCTP(流控制传输协议)分别保障通信安全与数据传输的可靠性。这项技术的核心价值在于能够建立低延迟、高隐私性的直接连接,无需依赖中心服务器中转数据,从而显著降低服务端带宽成本并提升用户体验。其典型应用场景包括远程桌面控制、在线协作工具、物联网(IoT)设备指令下发以及实时游戏状态同步等。本文聚焦于l 阅读详情

1.编写 ice 对象定义文件Printer.ice:

 

// **********************************************************************

//

// Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved.

//

// This copy of Ice is licensed to you under the terms described in the

// ICE_LICENSE file included in this distribution.

//

// **********************************************************************

 

#ifndef SIMPLE_ICE

#define SIMPLE_ICE

 

module Demo

{

 

    interface Printer

    {

        void printString(string s);

    };

 

};

 

#endif

2. 生成c++ 代理类:
在命令行输入 slice2cpp Printer.ice
生成:
// **********************************************************************
//
// Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved.
//
// This copy of Ice is licensed to you under the terms described in the
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
// Ice version 3.4.1
// <auto-generated>
//
// Generated from file `printer.ice'
//
// Warning: do not edit this file.
//
// </auto-generated>
#ifndef __printer_h__
#define __printer_h__
#include <Ice/LocalObjectF.h>
#include <Ice/ProxyF.h>
#include <Ice/ObjectF.h>
#include <Ice/Exception.h>
#include <Ice/LocalObject.h>
#include <Ice/Proxy.h>
#include <Ice/Object.h>
#include <Ice/Outgoing.h>
#include <Ice/OutgoingAsync.h>
#include <Ice/Incoming.h>
#include <Ice/Direct.h>
#include <IceUtil/ScopedArray.h>
#include <Ice/StreamF.h>
#include <Ice/UndefSysMacros.h>
#ifndef ICE_IGNORE_VERSION
#   if ICE_INT_VERSION / 100 != 304
#       error Ice version mismatch!
#   endif
#   if ICE_INT_VERSION % 100 > 50
#       error Beta header file detected
#   endif
#   if ICE_INT_VERSION % 100 < 1
#       error Ice patch level mismatch!
#   endif
#endif
namespace IceProxy
{
namespace Demo
{
class Printer;
}
}
namespace Demo
{
class Printer;
bool operator==(const Printer&, const Printer&);
bool operator<(const Printer&, const Printer&);
}
namespace IceInternal
{
::Ice::Object* upCast(::Demo::Printer*);
::IceProxy::Ice::Object* upCast(::IceProxy::Demo::Printer*);
}
namespace Demo
{
typedef ::IceInternal::Handle< ::Demo::Printer> PrinterPtr;
typedef ::IceInternal::ProxyHandle< ::IceProxy::Demo::Printer> PrinterPrx;
void __read(::IceInternal::BasicStream*, PrinterPrx&);
void __patch__PrinterPtr(void*, ::Ice::ObjectPtr&);
}
namespace Demo
{
class Callback_Printer_printString_Base : virtual public ::IceInternal::CallbackBase { };
typedef ::IceUtil::Handle< Callback_Printer_printString_Base> Callback_Printer_printStringPtr;
}
namespace IceProxy
{
namespace Demo
{
class Printer : virtual public ::IceProxy::Ice::Object
{
public:
    void printString(const ::std::string& s)
    {
        printString(s, 0);
    }
    void printString(const ::std::string& s, const ::Ice::Context& __ctx)
    {
        printString(s, &__ctx);
    }
    ::Ice::AsyncResultPtr begin_printString(const ::std::string& s)
    {
        return begin_printString(s, 0, ::IceInternal::__dummyCallback, 0);
    }
    ::Ice::AsyncResultPtr begin_printString(const ::std::string& s, const ::Ice::Context& __ctx)
    {
        return begin_printString(s, &__ctx, ::IceInternal::__dummyCallback, 0);
    }
    ::Ice::AsyncResultPtr begin_printString(const ::std::string& s, const ::Ice::CallbackPtr& __del, const ::Ice::LocalObjectPtr& __cookie = 0)
    {
        return begin_printString(s, 0, __del, __cookie);
    }
    ::Ice::AsyncResultPtr begin_printString(const ::std::string& s, const ::Ice::Context& __ctx, const ::Ice::CallbackPtr& __del, const ::Ice::LocalObjectPtr& __cookie = 0)
    {
        return begin_printString(s, &__ctx, __del, __cookie);
    }
    ::Ice::AsyncResultPtr begin_printString(const ::std::string& s, const ::Demo::Callback_Printer_printStringPtr& __del, const ::Ice::LocalObjectPtr& __cookie = 0)
    {
        return begin_printString(s, 0, __del, __cookie);
    }
    ::Ice::AsyncResultPtr begin_printString(const ::std::string& s, const ::Ice::Context& __ctx, const ::Demo::Callback_Printer_printStringPtr& __del, const ::Ice::LocalObjectPtr& __cookie = 0)
    {
        return begin_printString(s, &__ctx, __del, __cookie);
    }
    void end_printString(const ::Ice::AsyncResultPtr&);
    
private:
    void printString(const ::std::string&, const ::Ice::Context*);
    ::Ice::AsyncResultPtr begin_printString(const ::std::string&, const ::Ice::Context*, const ::IceInternal::CallbackBasePtr&, const ::Ice::LocalObjectPtr& __cookie = 0);
    
public:
    
    ::IceInternal::ProxyHandle<Printer> ice_context(const ::Ice::Context& __context) const
    {
    #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug
        typedef ::IceProxy::Ice::Object _Base;
        return dynamic_cast<Printer*>(_Base::ice_context(__context).get());
    #else
        return dynamic_cast<Printer*>(::IceProxy::Ice::Object::ice_context(__context).get());
    #endif
    }
    
    ::IceInternal::ProxyHandle<Printer> ice_adapterId(const std::string& __id) const
    {
    #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug
        typedef ::IceProxy::Ice::Object _Base;
        return dynamic_cast<Printer*>(_Base::ice_adapterId(__id).get());
    #else
        return dynamic_cast<Printer*>(::IceProxy::Ice::Object::ice_adapterId(__id).get());
    #endif
    }
    
    ::IceInternal::ProxyHandle<Printer> ice_endpoints(const ::Ice::EndpointSeq& __endpoints) const
    {
    #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug
        typedef ::IceProxy::Ice::Object _Base;
        return dynamic_cast<Printer*>(_Base::ice_endpoints(__endpoints).get());
    #else
        return dynamic_cast<Printer*>(::IceProxy::Ice::Object::ice_endpoints(__endpoints).get());
    #endif
    }
    
    ::IceInternal::ProxyHandle<Printer> ice_locatorCacheTimeout(int __timeout) const
    {
    #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug
        typedef ::IceProxy::Ice::Object _Base;
        return dynamic_cast<Printer*>(_Base::ice_locatorCacheTimeout(__timeout).get());
    #else
        return dynamic_cast<Printer*>(::IceProxy::Ice::Object::ice_locatorCacheTimeout(__timeout).get());
    #endif
    }
    
    ::IceInternal::ProxyHandle<Printer> ice_connectionCached(bool __cached) const
    {
    #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug
        typedef ::IceProxy::Ice::Object _Base;
        return dynamic_cast<Printer*>(_Base::ice_connectionCached(__cached).get());
    #else
        return dynamic_cast<Printer*>(::IceProxy::Ice::Object::ice_connectionCached(__cached).get());
    #endif
    }
    
    ::IceInternal::ProxyHandle<Printer> ice_endpointSelection(::Ice::EndpointSelectionType __est) const
    {
    #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug
        typedef ::IceProxy::Ice::Object _Base;
        return dynamic_cast<Printer*>(_Base::ice_endpointSelection(__est).get());
    #else
        return dynamic_cast<Printer*>(::IceProxy::Ice::Object::ice_endpointSelection(__est).get());
    #endif
    }
    
    ::IceInternal::ProxyHandle<Printer> ice_secure(bool __secure) const
    {
    #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug
        typedef ::IceProxy::Ice::Object _Base;
        return dynamic_cast<Printer*>(_Base::ice_secure(__secure).get());
    #else
        return dynamic_cast<Printer*>(::IceProxy::Ice::Object::ice_secure(__secure).get());
    #endif
    }
    
    ::IceInternal::ProxyHandle<Printer> ice_preferSecure(bool __preferSecure) const
    {
    #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug
        typedef ::IceProxy::Ice::Object _Base;
        return dynamic_cast<Printer*>(_Base::ice_preferSecure(__preferSecure).get());
    #else
        return dynamic_cast<Printer*>(::IceProxy::Ice::Object::ice_preferSecure(__preferSecure).get());
    #endif
    }
    
    ::IceInternal::ProxyHandle<Printer> ice_router(const ::Ice::RouterPrx& __router) const
    {
    #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug
        typedef ::IceProxy::Ice::Object _Base;
        return dynamic_cast<Printer*>(_Base::ice_router(__router).get());
    #else
        return dynamic_cast<Printer*>(::IceProxy::Ice::Object::ice_router(__router).get());
    #endif
    }
    
    ::IceInternal::ProxyHandle<Printer> ice_locator(const ::Ice::LocatorPrx& __locator) const
    {
    #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug
        typedef ::IceProxy::Ice::Object _Base;
        return dynamic_cast<Printer*>(_Base::ice_locator(__locator).get());
    #else
        return dynamic_cast<Printer*>(::IceProxy::Ice::Object::ice_locator(__locator).get());
    #endif
    }
    
    ::IceInternal::ProxyHandle<Printer> ice_collocationOptimized(bool __co) const
    {
    #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug
        typedef ::IceProxy::Ice::Object _Base;
        return dynamic_cast<Printer*>(_Base::ice_collocationOptimized(__co).get());
    #else
        return dynamic_cast<Printer*>(::IceProxy::Ice::Object::ice_collocationOptimized(__co).get());
    #endif
    }
    
    ::IceInternal::ProxyHandle<Printer> ice_twoway() const
    {
    #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug
        typedef ::IceProxy::Ice::Object _Base;
        return dynamic_cast<Printer*>(_Base::ice_twoway().get());
    #else
        return dynamic_cast<Printer*>(::IceProxy::Ice::Object::ice_twoway().get());
    #endif
    }
    
    ::IceInternal::ProxyHandle<Printer> ice_oneway() const
    {
    #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug
        typedef ::IceProxy::Ice::Object _Base;
        return dynamic_cast<Printer*>(_Base::ice_oneway().get());
    #else
        return dynamic_cast<Printer*>(::IceProxy::Ice::Object::ice_oneway().get());
    #endif
    }
    
    ::IceInternal::ProxyHandle<Printer> ice_batchOneway() const
    {
    #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug
        typedef ::IceProxy::Ice::Object _Base;
        return dynamic_cast<Printer*>(_Base::ice_batchOneway().get());
    #else
        return dynamic_cast<Printer*>(::IceProxy::Ice::Object::ice_batchOneway().get());
    #endif
    }
    
    ::IceInternal::ProxyHandle<Printer> ice_datagram() const
    {
    #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug
        typedef ::IceProxy::Ice::Object _Base;
        return dynamic_cast<Printer*>(_Base::ice_datagram().get());
    #else
        return dynamic_cast<Printer*>(::IceProxy::Ice::Object::ice_datagram().get());
    #endif
    }
    
    ::IceInternal::ProxyHandle<Printer> ice_batchDatagram() const
    {
    #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug
        typedef ::IceProxy::Ice::Object _Base;
        return dynamic_cast<Printer*>(_Base::ice_batchDatagram().get());
    #else
        return dynamic_cast<Printer*>(::IceProxy::Ice::Object::ice_batchDatagram().get());
    #endif
    }
    
    ::IceInternal::ProxyHandle<Printer> ice_compress(bool __compress) const
    {
    #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug
        typedef ::IceProxy::Ice::Object _Base;
        return dynamic_cast<Printer*>(_Base::ice_compress(__compress).get());
    #else
        return dynamic_cast<Printer*>(::IceProxy::Ice::Object::ice_compress(__compress).get());
    #endif
    }
    
    ::IceInternal::ProxyHandle<Printer> ice_timeout(int __timeout) const
    {
    #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug
        typedef ::IceProxy::Ice::Object _Base;
        return dynamic_cast<Printer*>(_Base::ice_timeout(__timeout).get());
    #else
        return dynamic_cast<Printer*>(::IceProxy::Ice::Object::ice_timeout(__timeout).get());
    #endif
    }
    
    ::IceInternal::ProxyHandle<Printer> ice_connectionId(const std::string& __id) const
    {
    #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug
        typedef ::IceProxy::Ice::Object _Base;
        return dynamic_cast<Printer*>(_Base::ice_connectionId(__id).get());
    #else
        return dynamic_cast<Printer*>(::IceProxy::Ice::Object::ice_connectionId(__id).get());
    #endif
    }
    
    static const ::std::string& ice_staticId();
private: 
    virtual ::IceInternal::Handle< ::IceDelegateM::Ice::Object> __createDelegateM();
    virtual ::IceInternal::Handle< ::IceDelegateD::Ice::Object> __createDelegateD();
    virtual ::IceProxy::Ice::Object* __newInstance() const;
};
}
}
namespace IceDelegate
{
namespace Demo
{
class Printer : virtual public ::IceDelegate::Ice::Object
{
public:
    virtual void printString(const ::std::string&, const ::Ice::Context*) = 0;
};
}
}
namespace IceDelegateM
{
namespace Demo
{
class Printer : virtual public ::IceDelegate::Demo::Printer,
                virtual public ::IceDelegateM::Ice::Object
{
public:
    virtual void printString(const ::std::string&, const ::Ice::Context*);
};
}
}
namespace IceDelegateD
{
namespace Demo
{
class Printer : virtual public ::IceDelegate::Demo::Printer,
                virtual public ::IceDelegateD::Ice::Object
{
public:
    virtual void printString(const ::std::string&, const ::Ice::Context*);
};
}
}
namespace Demo
{
class Printer : virtual public ::Ice::Object
{
public:
    typedef PrinterPrx ProxyType;
    typedef PrinterPtr PointerType;
    
    virtual ::Ice::ObjectPtr ice_clone() const;
    virtual bool ice_isA(const ::std::string&, const ::Ice::Current& = ::Ice::Current()) const;
    virtual ::std::vector< ::std::string> ice_ids(const ::Ice::Current& = ::Ice::Current()) const;
    virtual const ::std::string& ice_id(const ::Ice::Current& = ::Ice::Current()) const;
    static const ::std::string& ice_staticId();
    virtual void printString(const ::std::string&, const ::Ice::Current& = ::Ice::Current()) = 0;
    ::Ice::DispatchStatus ___printString(::IceInternal::Incoming&, const ::Ice::Current&);
    virtual ::Ice::DispatchStatus __dispatch(::IceInternal::Incoming&, const ::Ice::Current&);
    virtual void __write(::IceInternal::BasicStream*) const;
    virtual void __read(::IceInternal::BasicStream*, bool);
// COMPILERFIX: Stream API is not supported with VC++ 6
#if !defined(_MSC_VER) || (_MSC_VER >= 1300)
    virtual void __write(const ::Ice::OutputStreamPtr&) const;
    virtual void __read(const ::Ice::InputStreamPtr&, bool);
#endif
};
inline bool operator==(const Printer& l, const Printer& r)
{
    return static_cast<const ::Ice::Object&>(l) == static_cast<const ::Ice::Object&>(r);
}
inline bool operator<(const Printer& l, const Printer& r)
{
    return static_cast<const ::Ice::Object&>(l) < static_cast<const ::Ice::Object&>(r);
}
}
namespace Demo
{
template<class T>
class CallbackNC_Printer_printString : public Callback_Printer_printString_Base, public ::IceInternal::OnewayCallbackNC<T>
{
public:
    typedef IceUtil::Handle<T> TPtr;
    typedef void (T::*Exception)(const ::Ice::Exception&);
    typedef void (T::*Sent)(bool);
    typedef void (T::*Response)();
    CallbackNC_Printer_printString(const TPtr& obj, Response cb, Exception excb, Sent sentcb)
        : ::IceInternal::OnewayCallbackNC<T>(obj, cb, excb, sentcb)
    {
    }
};
template<class T> Callback_Printer_printStringPtr
newCallback_Printer_printString(const IceUtil::Handle<T>& instance, void (T::*cb)(), void (T::*excb)(const ::Ice::Exception&), void (T::*sentcb)(bool) = 0)
{
    return new CallbackNC_Printer_printString<T>(instance, cb, excb, sentcb);
}
template<class T> Callback_Printer_printStringPtr
newCallback_Printer_printString(const IceUtil::Handle<T>& instance, void (T::*excb)(const ::Ice::Exception&), void (T::*sentcb)(bool) = 0)
{
    return new CallbackNC_Printer_printString<T>(instance, 0, excb, sentcb);
}
template<class T> Callback_Printer_printStringPtr
newCallback_Printer_printString(T* instance, void (T::*cb)(), void (T::*excb)(const ::Ice::Exception&), void (T::*sentcb)(bool) = 0)
{
    return new CallbackNC_Printer_printString<T>(instance, cb, excb, sentcb);
}
template<class T> Callback_Printer_printStringPtr
newCallback_Printer_printString(T* instance, void (T::*excb)(const ::Ice::Exception&), void (T::*sentcb)(bool) = 0)
{
    return new CallbackNC_Printer_printString<T>(instance, 0, excb, sentcb);
}
template<class T, typename CT>
class Callback_Printer_printString : public Callback_Printer_printString_Base, public ::IceInternal::OnewayCallback<T, CT>
{
public:
    typedef IceUtil::Handle<T> TPtr;
    typedef void (T::*Exception)(const ::Ice::Exception& , const CT&);
    typedef void (T::*Sent)(bool , const CT&);
    typedef void (T::*Response)(const CT&);
    Callback_Printer_printString(const TPtr& obj, Response cb, Exception excb, Sent sentcb)
        : ::IceInternal::OnewayCallback<T, CT>(obj, cb, excb, sentcb)
    {
    }
};
template<class T, typename CT> Callback_Printer_printStringPtr
newCallback_Printer_printString(const IceUtil::Handle<T>& instance, void (T::*cb)(const CT&), void (T::*excb)(const ::Ice::Exception&, const CT&), void (T::*sentcb)(bool, const CT&) = 0)
{
    return new Callback_Printer_printString<T, CT>(instance, cb, excb, sentcb);
}
template<class T, typename CT> Callback_Printer_printStringPtr
newCallback_Printer_printString(const IceUtil::Handle<T>& instance, void (T::*excb)(const ::Ice::Exception&, const CT&), void (T::*sentcb)(bool, const CT&) = 0)
{
    return new Callback_Printer_printString<T, CT>(instance, 0, excb, sentcb);
}
template<class T, typename CT> Callback_Printer_printStringPtr
newCallback_Printer_printString(T* instance, void (T::*cb)(const CT&), void (T::*excb)(const ::Ice::Exception&, const CT&), void (T::*sentcb)(bool, const CT&) = 0)
{
    return new Callback_Printer_printString<T, CT>(instance, cb, excb, sentcb);
}
template<class T, typename CT> Callback_Printer_printStringPtr
newCallback_Printer_printString(T* instance, void (T::*excb)(const ::Ice::Exception&, const CT&), void (T::*sentcb)(bool, const CT&) = 0)
{
    return new Callback_Printer_printString<T, CT>(instance, 0, excb, sentcb);
}
}
#endif
3. 编写服务端代码:
///////////////////////////
// **********************************************************************
//
// Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved.
//
// This copy of Ice is licensed to you under the terms described in the
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
#include <Ice/Ice.h>
#include <Printer.h>
using namespace std;
using namespace Demo;
class PrinterI : public Printer
{
public:
    virtual void printString(const string &, const Ice::Current&);
};
void 
PrinterI::
printString(const string &s, const Ice::Current&)
{
    cout << s << endl;
}
int
main(int argc, char* argv[])
{
    int status = 0;
    int dummy;
    dummy = 0;
    Ice::CommunicatorPtr ic;
    try
    {
        Ice::PropertiesPtr props = Ice::createProperties();
        props->setProperty("Ice.ThreadPool.Server.Size" , "10"); //设置线程池数
        props->setProperty("Ice.ThreadPool.Server.SizeMax" , "20"); //设置最大线程池数
        
        Ice::InitializationData ini_data;
        ini_data.properties = props;
        //ic = Ice::initialize(argc, argv);
        //ic = Ice::initialize( dummy , 0 , props);
        ic = Ice::initialize(ini_data); 
        Ice::ObjectAdapterPtr adapter =
            ic->createObjectAdapterWithEndpoints("SimplePrinterAdapter", "tcp -p 10000");
        Ice::ObjectPtr object = new PrinterI;
        adapter->add(object, ic->stringToIdentity("SimplePrinter"));
        adapter->activate();
        ic->waitForShutdown();
    }
    catch(const Ice::Exception& e)
    {
        cerr << e << endl;
        status = 1;
    }
    catch(const char* msg)
    {
        cerr << msg << endl;
        status = 1;
    }
    if(ic)
    {
        try
        {
            ic->destroy();
        }
        catch(const Ice::Exception& e)
        {
            cerr << e << endl;
            status = 1;
        }
    }
    return status;
}
4.编写客户端代码:
// **********************************************************************
//
// Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved.
//
// This copy of Ice is licensed to you under the terms described in the
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
#include <Ice/Ice.h>
#include <Printer.h>
using namespace std;
using namespace Demo;
int
main(int argc, char * argv[])
{
    int status = 0;
    Ice::CommunicatorPtr ic;
    try
    {
        Ice::PropertiesPtr props = Ice::createProperties();
        props->setProperty("Ice.Default.Host", "127.0.0.1"); //设置线程池数
       
        Ice::InitializationData ini_data;
        ini_data.properties = props;
        //ic = Ice::initialize(argc, argv);
        ic = Ice::initialize(ini_data);
        Ice::ObjectPrx base = ic->stringToProxy("SimplePrinter:tcp -p 10000");
        PrinterPrx printer = PrinterPrx::checkedCast(base);
        if(!printer)
        {
            throw "Invalid proxy";
        }
        printer->printString("Hello World! by ken 2010");
    }
    catch(const Ice::Exception& ex)
    {
        cerr << ex << endl;
        status = 1;
    }
    catch(const char* msg)
    {
        cerr << msg << endl;
        status = 1;
    }
    if(ic)
    {
        try
        {
            ic->destroy();
        }
        catch (const Ice::Exception& ex)
        {
            cerr << ex << endl;
            status = 1;
        }
    }
    return status;
}
运行结果:
Hello World! by ken 2010

 

libdatachannel:轻量跨平台WebRTC数据通道实现与应用实战 WebRTC(Web实时通信)是一套支持浏览器与移动端进行点对点音视频和数据传输的开放标准协议栈,其核心价值在于无需插件即可实现低延迟、安全的实时通信。其技术原理基于ICE、STUN/TURN、DTLS-SRTP和SCTP等协议,通过NAT穿透建立直接连接,并保障传输安全。在工程实践中,原生WebRTC库(libwebrtc)常因庞大的体积、复杂的编译依赖和平台绑定问题,在嵌入式设备、IoT终端和原生桌面应用等非浏览器环境中集成困难。libdatachannel作为一款用现代C++17重写的轻量级、模块化W 阅读详情

相关推荐

ice性能测试,用于评估网络通讯库性能

基于互联网通讯引擎开发的测试程序,用于评估网络通讯核心在各种通讯协议,通讯方式、数据类型、数据大小、延时等性能参数的传输性能。

ZerocICE崩溃无法收到数据的问题,ICE无法收到数据不能解析,IceInternal::LocalExceptionWrapper错误SelectorTimerOutException问题Err

在建立Ice通信时,建议不要使用中文传输,就因为中文问题,调试了数天才解决。 IceInternal::LocalExceptionWrapper错误SelectorTimerOutException问题 发布端错误如下: 订阅端直接在接口函数处崩溃退出,通过调试定位到问题点… Ice.MarshalException error 详情是这样: 通过invalid utf8 string可以看到,很有可能是中文编码的问题。 后面经过调试,确实是因为中文编码问题引起,函数直接在响应接口处崩溃退出。 所以,

myhappyandy的博客 558

Ice-3.0.1库

Ice-3.0.1库,一个通信协议库的比较老的版本,比较稀缺的资源了

C++使用ICE实现两台主机通信实例

ice使用过程跟google protocol buffer、gsoap类似,都是先写一个类似配置文件的东西,然后使用提供的工具生成相应语言的代码。 ice先写一个后缀名为.ice的文件,然后使用slice2cpp.exe生产对应c++代码,如下module MCal { interface Cal { int add(int num1,int num2);

phymat.nico的专栏 2788

ICE第三方依赖库

ICE在linux系统编译,依赖很多第三库 附上编译知道网址http://blog.youkuaiyun.com/wxl1986622/article/details/7005031 Berkeley DB安装的时候,还需要:apt-get install libdb++-dev

ICE-开源库

github开源库依赖

SylixOS移植ICE库总结

1 ICE 简介       ICE(Internet Communications Engine)是一种面向对象的中间件平台,主要用于网络通讯。它为面向对象的“客户端-服务器”模型的应用提供了一组很好的工具和API接口。目前在全世界被应用于很多项目之中。ICE中间件号称标准统一,开源,跨平台,跨语言,分布式,安全,服务透明,负载均衡,面向对象,性能优越,防火期穿透,通讯屏蔽。因此相比Corba...

stone8761的专栏 739

【HDL系列】除法器(3)——基2 SRT算法

目录 一、除法表示 二、数字递归算法基础公式 三、QDS(Quotient Digit Selection)函数 四、基2 SRT算法 一、除法表示 除法被定义如下: 其中,x是被除数,d是除数,q是商,rem是余数。 商的精度由ulp(unit of last position)来决定: 如果ulp=1, 商q则是整数; 如果ulp=r^(-n),n是商数个数,r是所有输入操作数的基,此时商为小数。 二、数字递归算法基础公式 在使用数字递归算法(Digit Re...

纸上谈芯的专栏 8155

【ICE】ICE库下载链接及配置

ice - 3.6.1/3.6.3: 链接:https://pan.baidu.com/s/1tHMIjdGDdUlZ5b24aS87gg 提取码:x9ih 链接:https://pan.baidu.com/s/1ako-_Izi_jOB0g5n7kRoaQ 提取码:ml3j ICE(面向对象中间件): 网络通信引擎ICE(Internet Communications Engine...

yaotengjian的博客 2414

A股量化实战:用Python回测动量因子策略(附聚宽完整代码)

本文详细介绍了如何在A股市场使用Python和聚宽平台,实战回测一个动量因子量化交易策略。从环境搭建、数据获取到完整的策略代码实现与回测分析,手把手教你验证“强者恒强”的投资逻辑,并提供参数优化与实战避坑指南,助力量化新手迈出第一步。

weixin_29264201的博客 969

软件测试学习笔记(二)图覆盖

软件测试学习笔记(二)图覆盖 课程链接软件测试_中国大学MOOC 2.1 测试中的图 2.2 图覆盖准则 1、什么是图? 点的集合和边的集合。点或者结点,有穷非空的集合。边是点对。 2、图为什么在软件测试中具有重要地位? 所谓软件测试就是将软件变作一张图,然后覆盖它,不仅仅是软件,图更是计算机科学重要的结构。 3、软件测试中的图是如何得到的? 常见的图可以来自源代码,常见的是控制流图,还有各种各样...

DZFinder的博客 1420

knowledge base 知识库

某个项目,为他们的人力部门开发一个基于sales force知识库工具的内部网。几点总结如下: 既然是内部外,一定要限制只有内部人员才能访问。但是knowledge base知识库功能是建立在site网站上的工...

crfeng2005的博客 768

Verilog——反相器

反相器代码: module inv( A, Y );//A,Y是端口 //定义端口属性 input A; output Y; //定义输入输出关系 assign Y=~A;//Y等于A的反 endmodule //inv是module的名字

weixin_41788560的博客 9500

libdatachannel:构建原生跨平台实时通信系统的C++ WebRTC网络库架构解析

在当今数字化时代,实时通信已成为众多应用场景的核心需求,从视频会议到在线游戏,从物联网设备通信到金融交易系统。然而,原生应用与Web浏览器之间的实时通信一直面临着技术兼容性和性能优化的双重挑战。libdatachannel作为一款轻量级的C++ WebRTC网络库,通过实现W3C和IETF标准化的WebRTC数据通道、媒体传输和WebSocket功能,为开发者提供了一套高效、可靠的跨平台实时通信解

gitblog_00445的博客 741

Debezium报错处理系列之第112篇:Cannot replicate because the master purged required binary logs. Replicate the

Debezium报错处理系列之第112篇:Cannot replicate because the master purged required binary logs.

zhengzaifeidelushang的博客 726

UG NX二次开发(Python)-API函数介绍与应用实例(三)-UFLayer类操作

采用Python语言进行UG NX二次开发的帮助材料很少,采用录制的方法是一种比较容易实现的方式,但是使用UFun函数更容易上手,我们以后将逐渐的将Python-UFun的功能写进博客中,以便于有需要的人采纳和研究。本博客是为了入门需要,采用简单的创建长方体的功能来讲一下怎么使用Python语言开发。我们今天以移动长方体到某一个图层为例,讲一下UFLayer类中部分函数的使用。另外,我们长期提供UG NX二次开发的功能开发和咨询服务,有疑问可以私信博主或者在评论区讨论。

GimiGimmy 708

C++各大有名库的介绍——网络通信

在C++中,库的地位是非常高的。C++之父 Bjarne Stroustrup先生多次表示了设计库来扩充功能要好过设计更多的语法的言论。现实中,C++的库门类繁多,解决的问题也是极其广泛,库从轻量级到重量级的都有。不少都是让人眼界大开,亦或是望而生叹的思维杰作。由于库的数量非常庞大,而且限于笔者水平,其中很多并不了解。所以文中所提的一些库都是比较著名的大型库。 C++各大有名库的介绍——网络通信1、ACE参考网站:http://www.cs.wustl.edu/~schmidt/ACE.html  C++库

haohuang_hd的专栏 1875

使用Simulink对基于GaN器件的高频电源进行建模与仿真,重点在于优化其效率

本文介绍了基于Simulink的GaN器件高频电源仿真建模方法。通过7个步骤详细讲解系统构建过程:从创建模型、设置电源、配置GaN开关网络,到添加磁性元件、负载和控制器设计,最后进行仿真分析。重点探讨了效率优化策略,包括开关频率选择、磁性元件优化、散热设计改进及控制策略调整。该教程为GaN器件在电力电子系统中的应用提供了完整的仿真流程指导,有助于设计人员验证方案并优化性能。

amy_mhd的博客 233

在 Hermes Desktop 接入 Hindsight 长期记忆:只点三步的完整配置教程

每次新开一个对话窗口,你的 AI 助手都假装不认识你。上次的偏好、项目背景、踩过的坑,新窗口里全都不作数。把 Hindsight 接到 Hermes Desktop 上当长期记忆提供方,Agent 就能在每次对话前自动回忆、对话后自动留存,而且全程在设置面板里点选完成,不用碰配置文件,也不用开终端。做完之后你会发现:换个窗口再聊,它已经知道你是谁、在做什么。 ## 不用终端的三步配置 1. 拿

gitblog_00337的博客 252

uniapp - 使用web-view加载本地网页vue页面,用webview导入本地网页,uniAPP中使用web-view加载的本地及远程vue页面+双向通讯功能(兼容微信小程序、安卓苹果APP)

uniapp的App端web-view加载本地html,uniapp微信小程序webview加载本地HTML文件,在uniAPP中使用web-view加载的本地及远程vue页面且进行双向通讯,uni-app的web-view组件,支持加载远程网页,在app环境下,还支持加载本地HTML页面。uniapp WebView组件实现本地网页加载与通讯传值,uniAPP如何内嵌webView引入本地的vue网页示例代码,uniapp在web-view加载的本地及远程HTML中调用uni的API及网页和vue页面跳转

🏆 前端领域优质创作者 5226

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

3个核心技巧掌握libdatachannel:构建原生WebRTC应用的最佳实践

libdatachannel是一个基于C++17的WebRTC网络库,专为需要在原生应用中实现实时通信的开发者设计。它提供了数据通道、媒体传输和WebSocket功能,让你能够轻松构建跨平台的实时通信应用,无论是视频会议、在线游戏还是实时数据同步,都能找到完美的解决方案。 ## 🚀 为什么选择libdatachannel? 在众多WebRTC实现中,libdatachannel以其轻量级和跨

gitblog_00218的博客 495

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

如何用libdatachannel构建跨平台实时通信应用:从零到一的完整指南

在当今数字时代,实时通信已成为众多应用的核心需求。无论是视频会议、在线游戏、远程协作还是物联网设备通信,都需要高效可靠的数据传输机制。libdatachannel作为一个轻量级的C/C++ WebRTC网络库,为开发者提供了构建跨平台实时通信应用的强大工具。本文将为你深入解析这个开源项目的核心价值、应用场景和最佳实践。 --- ## 🎯 为什么选择libdatachannel:轻量级WebR

gitblog_00207的博客 827

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

type-challenges 第 108 题 Trim 解析:用模板字面量类型实现两端空白去除

`Trim` 是 type-challenges 仓库中编号 108 的中等难度(medium)挑战题,核心任务是在**类型层面**实现一个 `Trim<T>` 工具类型:输入一个精确的字符串字面量类型,输出去除两端空白字符(空格、制表符、换行)后的新字符串类型。本文以该题题面为主干,结合仓库中的模板文件、测试用例与相邻的 TrimLeft / TrimRight 两道系列题,讲解模板字面量类型(

gitblog_00444的博客 213

3步掌握libdatachannel:打造高效实时通信应用

你是否正在寻找一个轻量级的WebRTC解决方案,让原生应用与Web浏览器无缝通信?libdatachannel正是你的理想选择!这个基于C++17的开源WebRTC网络库,提供了数据通道、媒体传输和WebSocket功能,支持从Linux到Windows的多个平台。🚀 ## 🎯 为什么选择libdatachannel? libdatachannel的设计哲学是**简洁高效**。相比Goog

gitblog_00916的博客 238

终极指南:libjuice - 快速掌握C++蓝牙库开发技巧

在当今物联网和实时通信应用蓬勃发展的时代,**C++蓝牙库**的选择变得尤为关键。libjuice作为一款专为UDP交互式连接建立而设计的轻量级库,为开发者提供了强大的**低功耗蓝牙开发**解决方案,让复杂的网络通信变得简单高效。 ## 什么是libjuice?核心功能解析 libjuice是一个简化的交互式连接建立(ICE)协议实现,专门用于UDP流的双向通信和NAT穿透。这个库采用纯C语言

gitblog_00990的博客 952

基于测试的库合约验证:一种务实的形式化验证新范式

在软件工程中,形式化验证旨在通过数学方法确保程序正确性,但其为复杂第三方库编写完整合约的成本极高,难以落地。程序验证的核心在于建立可靠的规范(合约)与不变量,传统方法要求全局证明。而软件测试,尤其是符号执行与模糊测试,能以高置信度发现程序缺陷,虽无法证明无错,却是工程实践的关键。验证模测试库合约范式创新性地结合了两者优势:它不再追求为整个库提供完美证明,而是利用测试生成器为特定客户端合成“够用”的合约,这些合约需能通过形式化验证证明客户端安全,同时测试无法在资源内找到反例。这种方法将验证重心从“证明库绝对正

weixin_33674437的博客 308
上一篇: lua创始人的经验总结
下一篇: C代码优化案例
Monkeycn
博客等级 码龄25年 15粉丝 39原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值