Help us understand the problem. What is going on with this article?

C++兼SDL_netでHTTP通信するコード。400 Bad Requestの原因をコメントで指摘。

More than 3 years have passed since last update.
main.cpp
#include<windows.h>
#include<SDL_net.h>
#pragma comment(lib,"SDL2_net.lib")
int main(int argc, char_t *argv[]){
    IPaddress ip;
    TCPsocket server;
    if(!SDLNet_Init()){
        if(!SDLNet_ResolveHost(&ip,"k-db.com\0",80)){
            if(server=SDLNet_TCP_Open(&ip)){
                char    bufsend[]=
                    "GET https://www.google.co.jp/webhp?hl=ja\r\n"
                //原因1
                //リクエストで\nを改行コードとして誤って使っている。正しくは\r\nである。
                    "\r\n";
                //原因2
                //ヘッダの最後で一行を空け忘れている。
                //GETリクエストの末尾は改行+空行で〆るので"\r\n\r\n"となるべきである。
                SDLNet_TCP_Send(server,bufsend,sizeof(bufsend)+1);//+1は\0の分
                while(true){
                    char    bufrecv[256+1];
                    memset(bufrecv,0,sizeof(bufrecv));
                    if(SDLNet_TCP_Recv(server,bufrecv,sizeof(bufrecv))){
                        bufrecv[sizeof(bufrecv)-1]=0;
                        MessageBoxA(NULL,bufrecv,"title",MB_OK);
                    }else{
                        break;
                    }
                    //socketに溜まった返事を256byteずつ最後まで表示。
                }
                SDLNet_TCP_Close(server);
            }
        }
        SDLNet_Quit();
    }
    return  0;
}

SDLNet_TCP_Recvで1byteを読み込む動作を
1回,10回,100回,1000回,10000回繰り返す時間は
125,125,125,125,144(ms)だった。
だから多分SDLNet_TCP_Recvは内部のバッファに溜め込んでいる。
それを利用して早くパーサを作りたい。

2016/4/7追記
以上を応用して簡単なダウンローダを作った。
Content-lengthでもchunkedでもいける。

a.h
//tolua_end
#include<SDL_net.h>
#include<string>
#include<algorithm>
#pragma comment(lib,"SDL2_net.lib")
struct  HTTP{//tolua_export
    static  const   int SIZE=8192;
    char*   m_buff;
    TCPsocket   m_sckt;
    ~HTTP(){
        SDLNet_Quit();
        delete  m_buff;
    }
    struct  CURL{
        std::string m_host,m_path;
        CURL(const  char*t){
            std::string src(t);
            int n1=src.find("//",0)+2;
            int n2=src.find("/",n1);
            m_host=src.substr(n1,n2-n1);
            m_path=src.substr(n2);
        }
        IPaddress   resolve(){
            IPaddress ip={0};
            SDLNet_ResolveHost(&ip,m_host.c_str(),80);
            return  ip;
        }
    };
    bool    open(IPaddress i){
        return  (m_sckt=SDLNet_TCP_Open(&i))==NULL;
    }
    void    close(){
        SDLNet_TCP_Close(m_sckt);
    }
    void    sendhead(const  char*format,...){
        va_list arg;
        va_start(arg,format);
        int n=vsprintf_s(m_buff,SIZE,format,arg);
        if(n>=0){
            m_buff[n]=0;
            SDLNet_TCP_Send(m_sckt,m_buff,n+1);
        }
        va_end(arg);
    }
    char    recvchar(){
        char    t;
        while(SDLNet_TCP_Recv(m_sckt,&t,1)!=sizeof(t)){}
        return  t;
    }
    std::string recvhead(){
        std::string tmp;
        char    t[2]={0};
        for(int i=0;i<0xff;i++){
            t[0]=t[1];
            t[1]=recvchar();
            //順番大事
            if(((t[0]=='\r')&&(t[1]=='\n'))||((t[0]==':')&&(t[1]==' ')))break;
            if(*t)tmp.push_back(*t);
        }
        //比較前に小文字化
        std::transform(tmp.begin(),tmp.end(),tmp.begin(),tolower);
        return  tmp;
    }
    bool    recv(int size,void*p,void(*proc)(void*,void*,int n)){
        for(int n=0,i=0;i<size;i+=n){
            n=SDLNet_TCP_Recv(m_sckt,m_buff,min(size-i,SIZE));
            if(n){
                proc(p,m_buff,n);
            }else{
                return  true;
            }
        }
        return  false;
    }
    static  void    proc_fw(void*a,void*b,int c){
        fwrite(b,1,c,(FILE*)a);
    }
    //tolua_begin
    HTTP(){
        SDLNet_Init();
        m_buff=new  char[SIZE];
    }
    void    get(const   char*tmp,const  char*dst){
        CURL    url(tmp);
        if(open(url.resolve()))return;
        sendhead("GET %s HTTP/1.1\r\nhost: %s\r\n\r\n",url.m_path.c_str(),url.m_host.c_str());
        bool    chunked=false;
        signed  size;
        while(1){
            std::string a=recvhead();
            if(a==""){
                break;
            }
            if(a=="content-length"){
                size=atoi(recvhead().c_str());
            }
            if(a=="transfer-encoding"){
                if(recvhead()=="chunked"){
                    chunked=true;
                }
            }
        }
        FILE*   f;
        fopen_s(&f,dst,"wb");
        if(chunked){
            while(true){
                size=strtol(recvhead().c_str(),NULL,16);
                if(size>0){
                    recv(size,f,proc_fw);
                }else{
                    break;
                }
                //最後も改行
                recvhead();
            }
        }else{
            recv(size,f,proc_fw);//完成
        }
        fclose(f);
        close();
    }   
};

例)このページをdest.htmlとしてダウンロードする
HTTP h;
h.get("http://qiita.com/misumi3104/items/8e61ff68fc9fe68db533","dest.html")

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした