跨平台 C++ 纯socket 访问webapi json

webapi.h

#pragma once
#include <string>
#include <list>
#include <map>
class webapi
{
    class urlitem {
    public:
        urlitem() {
        }
        //std::string url;
        std::string fullpath; // http://www.pic98.com:8080/file/beautileg/samansha/201901011506.jpg#abc
        std::string query; // session=a231-dd33&token=aabbcc
        std::map<std::string, std::string> param; // {session =>a231-dd33,token=>aabbcc}
        std::string verb; // POST or GET
        std::string prot; // http
        std::string host; // www.pic98.com
        uint16_t port; // 8080
        std::string path; // /file/beautileg/samansha/201901011506.jpg
        std::string pathdir; // /file/beautileg/samasha
        std::string file; // 201901011506.jpg 
        std::list<std::string> ip;  // dns result for www.pic98.com
        std::string officalhost;
        std::list<std::string> aliases; // dns result for www.pic98.com
    };
private:
    webapi();
    ~webapi();
public:
    static webapi* me();
    std::string post(char* url,char* sid, char* par);
    bool urlparse(char* urlin,urlitem & out);
    std::string prepareheader(const urlitem* ui,char*,std::string post);
};


webapi.cpp

#include "webapi.h"
#include <vector>
#include <map>
#include <list>
#include <sstream>

#ifdef _WIN32
#include <winsock.h>
#include <share.h>
#include <io.h>
#include <direct.h> 
#else
#include <unistd.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/stat.h>


#include <unistd.h>
#include <sys/uio.h>


#include <sys/types.h>
#include <errno.h>


#endif


webapi::webapi(){
}


webapi::~webapi(){
}

webapi* webapi::me() {
    static webapi* wa = nullptr;
    if (wa == nullptr) {
        wa = new webapi();
    }
    return wa;
}

std::string UTF8_To_string(const std::string & str){
    int nwLen = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);
    wchar_t * pwBuf = new wchar_t[nwLen + 1];
    memset(pwBuf, 0, nwLen * 2 + 2);
    MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), pwBuf, nwLen);
    int nLen = WideCharToMultiByte(CP_ACP, 0, pwBuf, -1, NULL, NULL, NULL, NULL);
    char * pBuf = new char[nLen + 1];
    memset(pBuf, 0, nLen + 1);
    WideCharToMultiByte(CP_ACP, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL);
    std::string retStr = pBuf;
    delete[]pBuf;
    delete[]pwBuf;
    pBuf = NULL;
    pwBuf = NULL;
    return retStr;
}

std::string string_To_UTF8(const std::string & str){
    int nwLen = ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0);
    wchar_t * pwBuf = new wchar_t[nwLen + 1];
    ZeroMemory(pwBuf, nwLen * 2 + 2);
    ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.length(), pwBuf, nwLen);
    int nLen = ::WideCharToMultiByte(CP_UTF8, 0, pwBuf, -1, NULL, NULL, NULL, NULL);
    char * pBuf = new char[nLen + 1];
    ZeroMemory(pBuf, nLen + 1);
    ::WideCharToMultiByte(CP_UTF8, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL);
    std::string retStr(pBuf);
    delete[]pwBuf;
    delete[]pBuf;
    pwBuf = NULL;
    pBuf = NULL;
    return retStr;
}


std::string webapi::post(char* url,char* sid, char* par) {
    std::string ret="";
    struct sockaddr_in stSockAddr;
    std::vector<char> vbuf;
    char buf[2048] = { 0 };
    urlitem ui;
    urlparse(url, ui);
    int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    do {
        if (-1 == sockfd) {
            break;
        }
        int recvTimeout = 30 * 1000;  //30s
        int sendTimeout = 60 * 1000;  //30s
        setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&recvTimeout, sizeof(int));
        setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&sendTimeout, sizeof(int));
        memset(&stSockAddr, 0, sizeof(struct sockaddr_in));
        stSockAddr.sin_family = AF_INET;
        stSockAddr.sin_port = htons(ui.port);
        stSockAddr.sin_addr.s_addr = inet_addr(ui.ip.front().c_str());
        do {
            if (-1 == connect(sockfd, (const struct sockaddr *)&stSockAddr, sizeof(struct sockaddr_in))) {
                //WCLOG(LS_ERROR) << "socket connect error:" << errno;
                break;
            }
            
            std::string post1 = prepareheader(&ui,sid,par);
            std::string post = post1;// string_To_UTF8(post1);
            OutputDebugStringA(post.c_str());
            int left = post.length();
            int length = post.length();
            int len, i, j;
            while (left > 0) {
                len = send(sockfd, post.c_str() + length - left, left, 0);
                
                if (len <= 0) {
                    //WCLOG(LS_ERROR) << "socket send error:" << errno;
                    break;
                }
                left -= len;
            }
            if (len <= 0)
                break;
            std::string header;
            i = 0;
            while (true) {
                len = recv(sockfd, buf, sizeof(buf), 0);
                if (len <= 0) {
                    break;
                }
                vbuf.insert(vbuf.end(), buf, buf + len);
                if (vbuf.size() >= 4) {
                    for (; i < vbuf.size() - 3; i++) {
                        if (vbuf[i] == '\r' && vbuf[i + 1] == '\n' && vbuf[i + 2] == '\r' && vbuf[i + 3] == '\n') {
                            header.append(&vbuf[0], i);
                            //WCLOG(LS_ERROR) << "http header:" << header;
                            vbuf.erase(vbuf.begin(), vbuf.begin() + i + 4);
                            break;
                        }
                    }
                }
                if (!header.empty()) {
                    break;
                }
            }

            if (len <= 0)
                break;
            header.append("\r\n");
            size_t pos = 0, lastpos = 0;
            std::string temp;
            std::map<std::string, std::string> headers; // Content-Disposition
            std::string httpver;
            for (i = 0; i < header.length() - 1; i++) {
                if (header[i] == '\r' && header[i + 1] == '\n') {
                    temp = header.substr(lastpos, i - lastpos);
                    lastpos = i + 2;
                    for (j = 0; j < temp.length(); j++) {
                        if (temp[j] == ':') {
                            headers[temp.substr(0, j)] = temp.substr(j + 1);
                            break;
                        }
                    }
                    if (j == temp.length())
                        httpver = temp;
                }
            }
            std::vector<std::string> httpvers;
            lastpos = 0;
            httpver.append(" ");
            for (i = 0; i < httpver.length(); i++) {
                if (httpver[i] == ' ') {
                    std::string s0 = httpver.substr(lastpos, i - lastpos);
                    s0.erase(std::find(s0.begin(), s0.end(), ' '));
                    if (s0.length() > 0)
                        httpvers.push_back(s0);
                    lastpos = i;
                }
            }
            if (httpvers.size() < 2 || !(httpvers[1] == "200" )) {
                break;
            }
            std::map<std::string, std::string>::iterator iter = headers.find("Content-Length");
            if (iter != headers.end()) {
                int contentlength = atoi((*iter).second.c_str());
                while (contentlength > vbuf.size()) {
                    len = recv(sockfd, buf, sizeof(buf), 0);
                    if (len <= 0) {
                        break;
                    }
                    vbuf.insert(vbuf.end(), buf, buf + len);
                }
                ret = UTF8_To_string(std::string(&vbuf[0],vbuf.size()));
            }


        } while (false);
    } while (false);
    return ret;
}

std::string webapi::prepareheader(const urlitem* ui,char* sid,std::string post) {
    std::ostringstream os;
    os << "POST " << ui->path << " HTTP/1.1\r\n"
        << "Host:" << ui->host << "\r\n"
        << "Content-Type:" << "application/json; charset=utf-8\r\n"
        << "mster-token:" << sid << "\r\n"
        //<< "Connection:keep-alive\r\n"
        //<< "Upgrade-Insecure-Requests:1\r\n"
        << "User-Agent:Mozilla/5.0(Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3676.400 QQBrowser/10.4.3457.400\r\n"
        << "Accept:*/*\r\n"
        << "Content-Length:" << post.size() << "\r\n"
        << "Accept-Language: zh-CN,zh;q=0.9\r\n\r\n"
        << post;
    return os.str();
}

bool webapi::urlparse(char* urlin1, urlitem & out) {
    bool ret = false;
    int i = 0;
    std::string urlin(urlin1);
    if (strcmp(urlin.substr(0, 4).c_str(), "http") != 0)
        return false;
    int lastpos = 0;
    int pos = 0;
    std::string childs[10];
    std::string temp;
    int idx = 0;
    out.fullpath = urlin;
    pos = urlin.find('?', 0);
    if (pos >= 0) {
        out.fullpath = urlin.substr(0, pos);
        out.query = urlin.substr(pos + 1);
    }
    //
    lastpos = 0;
    for (i = 0; i < out.query.length(); i++) {
        if (out.query[i] == '&') {
            temp = out.query.substr(lastpos, i - lastpos);
            pos = temp.find('=', 0);
            if (pos >= 0) {
                out.param[temp.substr(0, pos)] = temp.substr(pos + 1);
            }
            lastpos = i + 1;
        }
    }
    temp = out.query.substr(lastpos);
    pos = temp.find('=', 0);
    if (pos >= 0) {
        out.param[temp.substr(0, pos)] = temp.substr(pos + 1);
    }
    lastpos = 0;
    idx = 0;
    for (i = 0; i < out.fullpath.length(); i++) {
        if (out.fullpath[i] == ':') {
            childs[idx] = out.fullpath.substr(lastpos, i - lastpos);
            lastpos = i + 1;
            idx++;
            break;
        }
    }
    out.prot = childs[0];
    out.port = 80;
    std::string fullpath = out.fullpath.substr(out.prot.length() + 3);
    pos = fullpath.find('/');
    if (pos >= 0) {
        out.host = fullpath.substr(0, pos);
        out.path = fullpath.substr(pos);
    }
    else if (pos = fullpath.find('\\') >= 0) {
        out.host = fullpath.substr(0, pos);
        out.path = fullpath.substr(pos);
    }
    pos = out.host.find(':');
    if (pos >= 0) {
        out.port = atoi(out.host.substr(pos + 1).c_str());
        out.host = out.host.substr(0, pos);
    }
    pos = out.path.rfind('/');
    if (pos >= 0) {
        out.file = out.path.substr(pos + 1);
    }
    else if (pos = out.path.rfind('\\') >= 0) {
        out.file = out.path.substr(pos + 1);
    }

    out.pathdir = out.path.substr(1, out.path.length() - out.file.length() - 1);

    struct hostent *hptr;
    char **pptr;
    if ((hptr = gethostbyname(out.host.c_str())) != nullptr) {
        if (hptr->h_name != nullptr)
            out.officalhost = hptr->h_name;
        for (pptr = hptr->h_aliases; *pptr != NULL; pptr++)
            out.aliases.push_back(*pptr);
        switch (hptr->h_addrtype) {
        case AF_INET:
            //case AF_INET6:
            pptr = hptr->h_addr_list;
            for (; *pptr != NULL; pptr++) {
                out.ip.push_back(inet_ntoa(*((in_addr *)*pptr)));
            }
            break;
        default:
            break;
        }
    }
    return true;
}

就这样调用吧

                std::thread t1([hWndThis,str1,strid,sessionid,userid, token]() {
                    std::string posturl = "http://www.pic98.com:8092/api/1.00/private";
                    if (token == "pulldlghis117") {
                        posturl = "http://www.pic98.com:8092/api/1.00/public";
                    }
                    std::string par;
                    std::stringstream ss;
                    ss << "{\"action\":\"caniplay\",\"id\":\"" << strid << "\"}";
                    std::string ret = webapi::me()->post((char*)posturl.c_str(),(char*)sessionid.ToString().c_str() ,(char*)ss.str().c_str());
                    char* pbuf1 = new char[str1.length() + 1];
                    strcpy(pbuf1, str1.c_str());
                    char* pbuf2 = new char[ret.length() + 1];
                    strcpy(pbuf2, ret.c_str());
                    ::PostMessage(hWndThis, WM_DLGFLVPLAYER_PLAY,(WPARAM)pbuf1,(LPARAM)pbuf2);
                });

                t1.detach();
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容