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

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

More than 3 years have passed since last update.

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

  • 下記ソースコードをコンパイルして実行します。
  • exeの横に表示したいファイルを置きます
  • http://localhost/ファイル名 をブラウザで表示します。
  • こうなります 01.JPG
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;
}

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

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

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

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
ユーザーは見つかりませんでした