操屁眼的视频在线免费看,日本在线综合一区二区,久久在线观看免费视频,欧美日韩精品久久综

新聞資訊

    有想學習c/c++編程的小伙伴可以私信小編哦~

    微軟的SDK已經出來很久了,有些小伙伴都曾經使用過,但是呢,還是有更多小伙伴沒有能夠弄清楚,今天我么就來看看在VS2013中怎么使用微軟的SDK吧!

    SDK讓你可以在C++中使用REST服務

    Visual Studio 2013中包括了C++ REST SDK version 1.0(也稱為Casablanca)。這個微軟的開源項目包括在CodePlex中,這個項目同時也利用了c++11中的新特點,設計了現代、異步、多平臺API,從而簡化了基于云端的編程。這是兩篇關于C++ REST SDK系列文章的第一篇,我會介紹如何通過SDK來使用REST服務。在下一篇文章中,我將介紹怎樣利用SDK來檢索和發送JSON文件。

    理解C++ REST SDK結構

    當你需要最佳性能時,你往往會在本地進行評估,那么C++就是最佳選擇之一。微軟認為C++在云端也是很有價值的,微軟最新的C++ REST SDK使得開發者可以通過C++來調用REST服務,從而滿足高性能和可擴展的要求。它讓你在C++中就可以調用REST服務或者是編寫其他與云計算相關的代碼。

    如果你正在使用C++來調用云端服務,但是你在回調函數中使用基于C語言的同步API,那么你沒用充分利用最新C++版本的高明之處。同時,你的代碼可能會很難閱讀和調試,同步的API使得你很難設計一個反應敏捷的用戶界面(UI)。大部分現代的WEB API都盡量減少不必要的樣板,并且提供異步方法。這些方法避免了C風格的回調函數的復雜性。

    比如,你正在使用C++,但是你利用它,通過調用一個同步的基于C的API,來進行HTTP的GET調用,那么這樣做的效率是不能和其他編程語言比如C#、Python相提并論的。微軟基于并行模式庫PPL研發了C++ REST SDK,并且利用了PPL的基于任務編程模型。無論何時,你利用C++ REST SDK執行異步操作,你都創建了一個新的PPL任務。為了讓C++ REST SDK可以移植到Linux平臺上,微軟確保PPL的關鍵部分可以在Linux上運行(并且使用GCC編譯)。因此,C++ REST SDK為依賴C++ 11的C++提供了一個并發運行環境。不同于使用回調函數,你可以優雅地編寫C++11標準的代碼來創建任務并且在其他任務執行完畢后,調度任務。如果你之前有過PPL的編程經驗,你會發現使用C++ REST SDK非常簡單。

    C++ REST SDK基于如下的四個底層棧或是API,這些棧或是API是基于不同操作系統提供的服務。(見Figure1)

    • WinHTTP:也稱為Microsoft Windows HTTP Services. 這是一個基于C語言的HTTP客戶端API。
    • PPL( Parallel Patterns Library的簡稱): 構成異步操作的編程模型。C++ REST SDK 在不同的Windows版本中使用WinHTTP 。
    • Boost.Asio: 跨平臺的C++庫,可以用于網絡編程或是底層的I/O編程。它提供了一致的異步模型。該庫采用現代C++方法。 C++ REST SDK 使用Boost.Asio 在Linux平臺上管理通信。
    • HTTP.sys: Windows 服務器端的HTTP。C++ REST SDK 在不同的Windows版本中使用 HTTP.sys。

    目前(寫成本文時),C++ REST SDK支持以下操作系統。特別注意,對Windows XP 系統和Windows Phone 8.x系統的支持,還在試驗階段。

    • Windows XP
    • Windows Vista
    • Windows 7
    • Windows 8.x
    • Windows Phone 8.x
    • Linux

    C++ REST SDK還包括如下部分,這些功能使用了不同的底層棧(見Figure 2):

    • Asynchronous streams and stream buffers(異步流和流緩沖區):這部分提供了一種基本的異步流,一種基本的異步流緩沖區,以及許多實現,比如異步文件流。有一些特定的互操作流,可以支持STL iostreams和C++ REST SDK異步流之間的互相操作。
    • HTTP client and listener(HTTP客戶端與監聽):HTTP客戶端允許你獲得與HTTP服務的連接,并且向服務器發送請求。 HTTP監聽讓你可以從指定的URI接收信息。
    • JSON parser and writer(JSON解析和寫入): JSON對于像C++之類的靜態語言是一個挑戰。 C++ REST SDK 中使用一個單獨的類(web::json::value)來表示JSON值,并且提供了必要的操作來幫助數據序列化 。你可以在代碼執行階段,聲明與JSON數值相關的類型。 C++ REST SDK 允許你通過JSON解析從流中讀取JSON數據,以及向流中寫入JSON數據。
    • TCP client and listener(TCP客戶端與監聽):TCP客戶端為TCP網絡服務提供了客戶端連接。TCP監聽會持續監聽TCP客戶端的網絡連接。TCP客戶端與監聽的最大優勢在于,可以完成非阻塞異步操作。但是,這些組件仍然在實驗階段。如果你要使用System.Net.Sockets::TcpListener或者System.Net.Sockets::TcpClient類,你要適應使用實驗版的TCP客戶端和監聽,以及它們提供的簡單的非阻塞異步操作。

    微軟的C++ REST SDK團隊計劃在不久的將來,在系統中增加如下部分:

    • Web Sockets client and listener. WEB Socket客戶端與箭筒
    • UDP client and listener. UDP 客戶端與監聽
    • Additional product-specific APIs built on top of the C++ REST SDK, such as Azure Storage, Mobile Services, and Bing Maps. 基于C++ REST SDK的其他產品專用API,比如Azure存儲,移動服務和Bing地圖。

    在Visual Studio 工程中使用C++ REST SDK

    在Visual Studio中創建使用SDK的項目并且成功生成該項目,你需要從CodePlex(http://casablanca.codeplex.com/)下載并安裝最新的SDK。在本文中,使用的是1.3版本。如果你下載的不是這一版本,你要在相應的配置值上做出調整。

    版本1.3中默認的安裝文件夾是C:\Program Files (x86)\Microsoft Cpp REST SDK for VS 2013 v1.3\SDK.VSProject子文件夾下有兩個屬性文件與你的Visual Studio工程相對應:CppRest.propsandversion.props.

    當你在Visual Studio中創建了你準備使用C++ REST SDK的工程之后,你必須按照下列步驟操作:

    • 將C++ REST SDK安裝文件夾下的兩個屬性文件,即VSProject子文件夾中的CppRest.props以及version.propswe文件,復制到你創建Visual Studio項目的主文件夾中。
    • 打開cpprest.props屬性文件,其中的兩個屬性問價可能有錯誤值:CppRestSDKPathandCppRestRuntimeBaseFileName.如下圖所示,如果你找到了下面的兩行,你要將其中110替換為120。在64-bit的Windows版本中,規定了C++ REST SDK基本安裝文件夾的屬性值是InstallDir,這個屬性值在HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\CppRestSDK\OpenSourceRelease0\v1.3\SDK中.不幸的是,一些SDK版本不會檢查屬性值,如果你不用上述的120替換掉110這個值,就不能成功生成對應工程。因為,不替換對應值的話,在生成項目的過程中,找不到正確的注冊表入口。C++ REST SDK中提供的樣例,也存在這樣的問題,因此你必須在屬性文件中替換相應值,才能正確生成項目文件。

    未修改屬性文件:

    <CppRestSDKPath>$([MSBuild]::GetRegistryValue(`HKEY_LOCAL_MACHINE\Software\Microsoft\CppRestSDK\OpenSourceRelease0\v$(CppRestSDKVersionString)\SDK`, `InstallDir`))</CppRestSDKPath>

    <CppRestRuntimeBaseFileName>$(CppRestBaseFileName)110$(DebugFileSuffix)_$(CppRestSDKVersionFileSuffix)</CppRestRuntimeBaseFileName>

    修改后的屬性文件:

    <CppRestSDKPath>$([MSBuild]::GetRegistryValue(`HKEY_LOCAL_MACHINE\Software\Microsoft\CppRestSDK\OpenSourceRelease0\v$(CppRestSDKVersionString)\SDK`, `InstallDir`))</CppRestSDKPath>

    <CppRestRuntimeBaseFileName>$(CppRestBaseFileName)120$(DebugFileSuffix)_$(CppRestSDKVersionFileSuffix)</CppRestRuntimeBaseFileName>

    • 現在,打開在你喜歡的文本編輯器中,打開你的C++項目對應Visual Studio 中的vcxproj文件,在Project中加入下面一行。這樣,你的項目就可以包含CppRest.props中的定義。值得注意的是,CppRest.props中有一行是引入已經拷貝的CppRest.props配置文件:<Import Project=”CppRest.props” />
    • 在Visual Studio中打開對應項目,打開項目屬性。在Configuration Properties | VC++ Directories中的include Directories屬性中加入C++ REST SDK安裝路徑下include子文件夾的完整路徑。如果你使用的是默認安裝文件夾,你需要添加的屬性值為C:\Program Files (x86)\Microsoft Cpp REST SDK for VS 2013 v1.3\SDK\include。
    • 在Configuration Properties | VC++ Directories中Library Directories屬性中加入C++ REST SDK安裝路徑下lib子文件夾的完整路徑.如果你使用的是默認安裝文件夾,那么你需要添加的屬性值為C:\Program Files (x86)\Microsoft Cpp REST SDK for VS 2013 v1.3\SDK\lib.
    • 添加C++ REST SDK庫。具體來說,在Configuration Properties | Linker | Input中的Additional Dependencies加入cpprest120d_1_3.lib文件。

    現在,你的C++項目就可以開始和C++ REST SDK一起工作了。(你也可以在 Package Manager Console控制臺,通過運行命令Install-Package cpprestsdk來安裝最新版本的C++ REST SDK,同時,使用相應包來向已經建立的項目添加C++ REST SDK并完成相應設置。但是,在新項目中使用最新版本SDK的最佳方法,是按照上文所述的步驟進行配置和添加。)

    最后,小編在說一句,有需要VS2013或者VS2017學習c/c++編程的小伙伴可以私信我哦~小編這里有免費資源可以送給你的!

    本文分享自華為云社區《華為云短信服務教你用C++實現Smgp協議-云社區-華為云》,作者:張儉。

    引言&協議概述

    中國聯合網絡通信有限公司短消息網關系統接口協議(SGIP)是中國網通為實現短信業務而制定的一種通信協議,全稱叫做Short Message Gateway Interface Protocol,用于在短消息網關(SMG)和服務提供商(SP)之間、短消息網關(SMG)和短消息網關(SMG)之間通信。

    Perl的IO::Async模塊提供了一套簡潔的異步IO編程模型。

    SGIP 協議基于客戶端/服務端模型工作。由客戶端(短信應用,如手機,應用程序等)先和短信網關(SMG Short Message Gateway)建立起 TCP 長連接,并使用 SGIP 命令與SMG進行交互,實現短信的發送和接收。在SGIP協議中,無需同步等待響應就可以發送下一個指令,實現者可以根據自己的需要,實現同步、異步兩種消息傳輸模式,滿足不同場景下的性能要求。

    時序圖

    連接成功,發送短信

    連接成功,從SMGW接收到短信

    協議幀介紹

    SGIP Header

    • Message Length:長度為4字節,整個PDU的長度,包括Header和Body。
    • Command ID:長度為4字節,用于標識PDU的類型(例如,Login、Submit等)。
    • Sequence Number:長度為8字節,序列號,用來匹配請求和響應。

    使用C++實現SMGP協議棧里的建立連接

    ├── CMakeLists.txt
    ├── examples
    │   └── smgp_client_login_example.cpp
    └── include
        └── sgipcpp
            ├── BoundAtomic.h
            ├── Client.h
            ├── Protocol.h
            └── impl
                ├── BoundAtomic.cpp
                ├── Client.cpp
                └── Protocol.cpp
    
    

    CMakeLists.txt:用來生成Makefile和編譯項目

    examples:存放示例代碼

    • smgp_client_login_example.cpp:存放Smgp的login樣例

    include/sgipcpp:包含所有的C++頭文件和實現文件

    • BoundAtomic.h:遞增工具類,用來生成SequenceId
    • Client.h:Smgp定義,負責與Smgp服務進行通信,例如建立連接、發送短信等
    • Protocol.h:存放PDU,編解碼等
    • impl/BoundAtomic.cpp:BoundAtomic類的實現
    • impl/Client.cpp:Client類的實現
    • impl/Protocol.cpp:Protocol中相關函數的實現

    實現SequenceId遞增

    SequenceId是從1到0x7FFFFFFF的值,使用**BoundAtomic**類實現遞增:

    頭文件

    #ifndef BOUNDATOMIC_H
    #define BOUNDATOMIC_H
    
    #include <atomic>
    #include <cassert>
    
    class BoundAtomic {
    public:
        BoundAtomic(int min, int max);
        int next_val();
    
    private:
        int min_;
        int max_;
        std::atomic<int> integer_;
    };
    
    #endif //BOUNDATOMIC_H
    

    內容

    #include "sgipcpp/BoundAtomic.h"
    
    BoundAtomic::BoundAtomic(int min, int max) : min_(min), max_(max), integer_(min) {
        assert(min <=max);
    }
    
    int BoundAtomic::next_val() {
        int current=integer_.load();
        int next;
        do {
            next=current >=max_ ? min_ : current + 1;
        } while (!integer_.compare_exchange_strong(current, next));
    
        return next;
    }
    

    實現SMGP PDU以及編解碼函數

    在**Protocol.h**中定義SMGP PDU以及編解碼函數:

    頭文件

    #ifndef PROTOCOL_H
    #define PROTOCOL_H
    
    #include <cstdint>
    #include <vector>
    
    constexpr uint32_t SGIP_BIND=0x00000001;
    constexpr uint32_t SGIP_BIND_RESP=0x80000001;
    constexpr uint32_t SGIP_UNBIND=0x00000002;
    constexpr uint32_t SGIP_UNBIND_RESP=0x80000002;
    constexpr uint32_t SGIP_SUBMIT=0x00000003;
    constexpr uint32_t SGIP_SUBMIT_RESP=0x80000003;
    constexpr uint32_t SGIP_DELIVER=0x00000004;
    constexpr uint32_t SGIP_DELIVER_RESP=0x80000004;
    constexpr uint32_t SGIP_REPORT=0x00000005;
    constexpr uint32_t SGIP_REPORT_RESP=0x80000005;
    constexpr uint32_t SGIP_ADDSP=0x00000006;
    constexpr uint32_t SGIP_ADDSP_RESP=0x80000006;
    constexpr uint32_t SGIP_MODIFYSP=0x00000007;
    constexpr uint32_t SGIP_MODIFYSP_RESP=0x80000007;
    constexpr uint32_t SGIP_DELETESP=0x00000008;
    constexpr uint32_t SGIP_DELETESP_RESP=0x80000008;
    constexpr uint32_t SGIP_QUERYROUTE=0x00000009;
    constexpr uint32_t SGIP_QUERYROUTE_RESP=0x80000009;
    constexpr uint32_t SGIP_ADDTELESEG=0x0000000A;
    constexpr uint32_t SGIP_ADDTELESEG_RESP=0x8000000A;
    constexpr uint32_t SGIP_MODIFYTELESEG=0x0000000B;
    constexpr uint32_t SGIP_MODIFYTELESEG_RESP=0x8000000B;
    constexpr uint32_t SGIP_DELETETELESEG=0x0000000C;
    constexpr uint32_t SGIP_DELETETELESEG_RESP=0x8000000C;
    constexpr uint32_t SGIP_ADDSMG=0x0000000D;
    constexpr uint32_t SGIP_ADDSMG_RESP=0x8000000D;
    constexpr uint32_t SGIP_MODIFYSMG=0x0000000E;
    constexpr uint32_t SGIP_MODIFYSMG_RESP=0x8000000E;
    constexpr uint32_t SGIP_DELETESMG=0x0000000F;
    constexpr uint32_t SGIP_DELETESMG_RESP=0x8000000F;
    constexpr uint32_t SGIP_CHECKUSER=0x00000010;
    constexpr uint32_t SGIP_CHECKUSER_RESP=0x80000010;
    constexpr uint32_t SGIP_USERRPT=0x00000011;
    constexpr uint32_t SGIP_USERRPT_RESP=0x80000011;
    constexpr uint32_t SGIP_TRACE=0x00001000;
    constexpr uint32_t SGIP_TRACE_RESP=0x80001000;
    
    struct Header {
        uint32_t total_length;
        uint32_t command_id;
        uint64_t sequence_number;
    };
    
    struct Bind {
        char login_type;
        char login_name[16];
        char login_passwd[16];
        char reserve[8];
    };
    
    struct BindResp {
        char result;
        char reserve[8];
    };
    
    struct Pdu {
        Header header;
        union {
            Bind bind;
            BindResp bind_resp;
        };
    };
    
    size_t lengthBind();
    std::vector<uint8_t> encodePdu(const Pdu& pdu);
    Pdu decodePdu(const std::vector<uint8_t>& buffer);
    
    #endif //PROTOCOL_H
    

    內容

    #include "sgipcpp/Protocol.h"
    #include <cstring>
    #include <ostream>
    #include <stdexcept>
    #include <sys/_endian.h>
    
    size_t lengthBind(const Bind& bind) {
        return 1 + 16 + 16 + 8;
    }
    
    void encodeBind(const Bind& bind, std::vector<uint8_t>& buffer) {
        size_t offset=16;
    
        buffer[offset++]=bind.login_type;
        std::memcpy(buffer.data() + offset, bind.login_name, 16);
        offset +=16;
        std::memcpy(buffer.data() + offset, bind.login_passwd, 16);
        offset +=16;
        std::memcpy(buffer.data() + offset, bind.reserve, 8);
    }
    
    BindResp decodeBindResp(const std::vector<uint8_t>& buffer) {
        BindResp bindResp;
    
        size_t offset=0;
    
        offset +=sizeof(uint32_t);
        offset +=sizeof(uint32_t);
    
        bindResp.result=buffer[offset++];
        std::memcpy(bindResp.reserve, buffer.data() + offset, sizeof(bindResp.reserve));
    
        return bindResp;
    }
    
    std::vector<uint8_t> encodePdu(const Pdu& pdu) {
        size_t body_length;
        switch (pdu.header.command_id) {
            case SGIP_BIND:
                body_length=lengthBind(pdu.bind);
                break;
            default:
                throw std::runtime_error("Unsupported command ID for encoding");
        }
    
        std::vector<uint8_t> buffer(body_length + 16);
        uint32_t total_length=htonl(body_length + 16);
        std::memcpy(buffer.data(), &total_length, 4);
    
        uint32_t command_id=htonl(pdu.header.command_id);
        std::memcpy(buffer.data() + 4, &command_id, 4);
    
        uint32_t sequence_number=htonl(pdu.header.sequence_number);
        std::memcpy(buffer.data() + 8, &sequence_number, 8);
    
        switch (pdu.header.command_id) {
            case SGIP_BIND:
                encodeBind(pdu.bind, buffer);
            break;
            default:
                throw std::runtime_error("Unsupported command ID for encoding");
        }
    
        return buffer;
    }
    
    Pdu decodePdu(const std::vector<uint8_t>& buffer) {
        Pdu pdu;
    
        uint32_t command_id;
        std::memcpy(&command_id, buffer.data(), 4);
        pdu.header.command_id=ntohl(command_id);
    
        uint64_t sequence_number;
        std::memcpy(&sequence_number, buffer.data() + 8, 8);
        pdu.header.sequence_number=ntohl(sequence_number);
    
        switch (pdu.header.command_id) {
            case SGIP_BIND_RESP:
                pdu.bind_resp=decodeBindResp(buffer);
                break;
            default:
                throw std::runtime_error("Unsupported command ID for decoding");
        }
    
        return pdu;
    }
    

    實現客戶端和登錄方法

    在**Client**中實現客戶端和登錄方法:

    頭文件

    #ifndef CLIENT_H
    #define CLIENT_H
    
    #include "BoundAtomic.h"
    #include "Protocol.h"
    #include "asio.hpp"
    #include <string>
    
    class Client {
    public:
        Client(const std::string& host, uint16_t port);
        ~Client();
    
        void connect();
        BindResp bind(const Bind& bind_request);
        void close();
    
    private:
        std::string host_;
        uint16_t port_;
        asio::io_context io_context_;
        asio::ip::tcp::socket socket_;
        BoundAtomic* sequence_number_;
    
        void send(const std::vector<uint8_t>& data);
        std::vector<uint8_t> receive(size_t length);
    };
    
    #endif //CLIENT_H
    

    內容

    #include "sgipcpp/Client.h"
    #include <iostream>
    
    Client::Client(const std::string& host, uint16_t port)
        : host_(host), port_(port), socket_(io_context_) {
        sequence_number_=new BoundAtomic(1, 0x7FFFFFFF);
    }
    
    Client::~Client() {
        close();
        delete sequence_number_;
    }
    
    void Client::connect() {
        asio::ip::tcp::resolver resolver(io_context_);
        asio::connect(socket_, resolver.resolve(host_, std::to_string(port_)));
    }
    
    BindResp Client::bind(const Bind& bind_request) {
        Pdu pdu;
        pdu.header.total_length=sizeof(Bind) + sizeof(Header);
        pdu.header.command_id=SGIP_BIND;
        pdu.header.sequence_number=sequence_number_->next_val();
        pdu.bind=bind_request;
    
        send(encodePdu(pdu));
    
        auto length_data=receive(4);
        uint32_t total_length=ntohl(*reinterpret_cast<uint32_t*>(length_data.data()));
    
        auto resp_data=receive(total_length - 4);
        Pdu resp_pdu=decodePdu(resp_data);
        return resp_pdu.bind_resp;
    }
    
    void Client::close() {
        socket_.close();
    }
    
    void Client::send(const std::vector<uint8_t>& data) {
        asio::write(socket_, asio::buffer(data));
    }
    
    std::vector<uint8_t> Client::receive(size_t length) {
        std::vector<uint8_t> buffer(length);
        asio::read(socket_, asio::buffer(buffer));
        return buffer;
    }
    

    運行example,驗證連接成功

    #include "sgipcpp/Client.h"
    #include <iostream>
    
    int main() {
        try {
            Client client("127.0.0.1", 8801);
    
            client.connect();
            std::cout << "Connected to the server." << std::endl;
    
            Bind bindRequest;
            bindRequest.login_type=1;
            std::string login_name="1234567890123456";
            std::string login_password="1234567890123456";
            std::string reserve="12345678";
            std::copy(login_name.begin(), login_name.end(), bindRequest.login_name);
            std::copy(login_password.begin(), login_password.end(), bindRequest.login_passwd);
            std::copy(reserve.begin(), reserve.end(), bindRequest.reserve);
    
            BindResp response=client.bind(bindRequest);
            if (response.result==0) {
                std::cout << "Login successful." << std::endl;
            } else {
                std::cout << "Login failed with result code: " << static_cast<int>(response.result) << std::endl;
            }
    
            client.close();
            std::cout << "Connection closed." << std::endl;
    
        } catch (const std::exception& e) {
            std::cerr << "Error: " << e.what() << std::endl;
        }
    
        return 0;
    }
    

    相關開源項目

    • netty-codec-sms 存放各種SMS協議(如cmpp、sgip、smpp)的netty編解碼器
    • sms-client-java 存放各種SMS協議的Java客戶端
    • sms-server-java 存放各種SMS協議的Java服務端
    • cmpp-python cmpp協議的python實現
    • cngp-zig cmpp協議的python實現
    • sgip-cpp sgip協議的cpp實現
    • smgp-perl smgp協議的perl實現
    • smpp-rust smpp協議的rust實現

    總結

    本文簡單對SGIP協議進行了介紹,并嘗試用C++實現協議棧,但實際商用發送短信往往更加復雜,面臨諸如流控、運營商對接、傳輸層安全等問題,可以選擇華為云消息&短信(Message & SMS)服務通過HTTP協議接入華為云短信服務是華為云攜手全球多家優質運營商和渠道,為企業用戶提供的通信服務。企業調用API或使用群發助手,即可使用驗證碼、通知短信服務。

    關注#華為云開發者聯盟# 點擊下方,第一時間了解華為云新鮮技術~

    華為云博客_大數據博客_AI博客_云計算博客_開發者中心-華為云

網站首頁   |    關于我們   |    公司新聞   |    產品方案   |    用戶案例   |    售后服務   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權所有