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

```cpp: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"
				//原因１
				//リクエストで\nを改行コードとして誤って使っている。正しくは\r\nである。
					"\r\n";
				//原因２
				//ヘッダの最後で一行を空け忘れている。
				//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でもいける。

```cpp: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")