簡単なHTTPサーバーをSDL_netで作る2

HTTPサーバーとして必要最低限の処理を書いたつもりです。

- 下記ソースコードをコンパイルして実行します。
- exeの横に表示したいファイルを置きます
- http://localhost/ファイル名 をブラウザで表示します。
- こうなります
![01.JPG](https://qiita-image-store.s3.amazonaws.com/0/118083/50907ac6-ec30-af91-6e20-65f843933670.jpeg)


```cpp:main.cpp

#include<stdio.h>
#include<SDL_net.h>
#include<string>
#include<vector>
#include<algorithm>
//#pragma comment(lib,"SDL2_net.lib")
//#pragma comment(lib,"SDL2main.lib")
//#pragma comment(lib,"SDL2.lib")
using   namespace   std;

//####関数####
//区切り文字pまで受信する。
//input
//  t:受信先文字列
//  s:受信用ソケット
//  p:区切り文字(末端\0も判定対象)
//  m:無視する文字(\rが邪魔なのだ)
//output
//  区切られた文字

char    recv(string&t,TCPsocket s,char*p="\n",char*m="\r"){
	t.clear();
	while(true){
		char    c;
		if(SDLNet_TCP_Recv(s,&c,1)>0){
			for(int i=0;true;i++){
				if(c==p[i])return   c;
				if(!p[i])break;
			}
			for(int i=0;true;i++){
				if(c==m[i]){break;}
				if(!m[i]){t+=c;break;}
			}
		}else{
			return	-1;
		}
	}
	return  0;
}
//####関数####
//拡張子からMINEタイプを返す
//input
//  url:ファイル名
//output
//  mineタイプ名
string	mine(string url){
	string	e=url.substr(url.find_last_of(".")+1);
	transform(e.begin(),e.end(),e.begin(),tolower);
	#define	mine(a,b)	if(e==a)return	b;
	mine("txt","text/plain");
	mine("htm","text/html");
	mine("html","text/html");
	mine("xml","text/xml");
	mine("js","text/javascript");
	mine("css","text/css");
	mine("gif","image/gif");
	mine("jpg","image/jpeg");
	mine("jpg","image/jpg");
	mine("pdf","application/pdf");
	#undef	mine
	return	"text/plain";
}
int main(int argc, char *argv[]){
	IPaddress ip;
	TCPsocket accepting,accepted;
	//####注意####ヘッダと中身は一行空ける。
	const   char    bufsend[]=
		"HTTP/1.1 200 OK\n"
		"Accept-Ranges: bytes\n"
		"Content-Length: 42\n"
		"Connection: Keep-Alive\n"
		"Content-Type: text/html\n"
		"\n"
		"<html><body><p>success</p></body></html>\n";
	if(!SDLNet_Init()){
		if(!SDLNet_ResolveHost(&ip,NULL,80)){
			if(accepting=SDLNet_TCP_Open(&ip)){
				//####注意####accepted!=acceptingであり。acceptedを使う。
				//####注意####SDLNet_TCP_Acceptは何度も呼び出すべし。
				while(true){
					while((accepted=SDLNet_TCP_Accept(accepting))==NULL){
						SDL_Delay(100);
					}
					bool	keep,gzip;
					vector<string>value;
					string  t;
					//get
					if(recv(t,accepted," ")){
						//value
						value.clear();
						while(true){
							char	c=recv(t,accepted,"? ");
							value.push_back(t);
							if(c!='?'){
								break;
							}
						}
						recv(t,accepted);
						while(true){//一行毎に回す
							recv(t,accepted," \n");
							if(t==""){
								break;//最後の行。
							}else   if(t=="Connection:"){
								recv(t,accepted);
								keep=(t=="keep-alive")||(t=="Keep-Alive");
							}else   if(t=="Accept-Encoding:"){
								gzip=false;
								while(true){
									if(recv(t,accepted,", \n")=='\n'){
										break;
									}else   if(t=="gzip"){
										gzip=true;
									}
								}
							}else{
								recv(t,accepted);
							}
						}
						FILE*f;
						if(fopen_s(&f,value[0].c_str()+1,"rb")){
							char	t[]="HTTP/1.1 404 not found\nAccept-Ranges: bytes\nContent-Length: 42\nConnection: Close\nContent-Type: text/html\n\n<html><body><p>failed.</p></body></html>\n";
							SDLNet_TCP_Send(accepted,t,sizeof(t));
						}else{
							char	t[512];
							fseek(f,0,SEEK_END);
							SDLNet_TCP_Send(accepted,t,sprintf_s(t,sizeof(t),"HTTP/1.1 200 OK\nAccept-Ranges: bytes\nContent-Length: %d\nConnection: Close\nContent-Type: %s\n\n",(int)ftell(f),mine(value[0]).c_str()));
							fseek(f,0,SEEK_SET);
							while(!feof(f))SDLNet_TCP_Send(accepted,t,fread(t,1,sizeof(t),f));
						}
					}else{
						printf("close");
					}
					SDLNet_TCP_Close(accepted);
				}
				SDLNet_TCP_Close(accepting);
			}
		}
		SDLNet_Quit();
	}
	return  0;
}

```

１ページに必要な全ての通信を終えた後もブラウザが再接続を試みるので多分複数のクライアントのリクエストには耐えられない。
まともなサーバーはどう処理しているのか知りたい。

上記は今解決しましたggったらマルチスレッドを使うみたいです。

マルチスレッド化とアプリケーションサーバー化を次回の課題とします。