乐趣区

关于c:Linux网络开发必学教程28浏览器请求响应实现

文件服务器架构

职责定义

  • 主线程

    • 命令行输出,管理员可管制服务端工作状态
  • 监听线程

    • 服务端启动后对客户端连贯进行监听的工作环境
  • 通信线程

    • 客户端连贯胜利后与服务端的数据交互环境

主线程

int main(int argc, char *argv)
{if (argc >=2) {DIR *dir = opendir(argv[1]);
        if (dir != NULL) {close(dir);
            Run(argv[1]);
        }
    } 

    printf("Can not launch File Server, need a valid director as root.\n");

    return 0;
}
if (*line) {char *cmd = FormatByChar(line, ' ');  // 此处的作用次要为去除前后空格
    int done = 0;

    for (i=0; i<DIM(g_handler); ++i) {if (strcmp(g_handler[i].cmd, cmd) == 0) {g_handler[i].handler(cmd);
            done = 1;
            break;
        }
    }
    
    if (!done) {printf("\'%s\'can NOT be parser!\n", cmd);
    }

    free(cmd);
}

交互流程一

交互流程二

监护线程

static void *Server_Thread(void *arg)
{while (TcpServer_IsValid(arg)) {TcpClient *client = TcpServer_Accept(arg);

        if (client &&(g_status != PAUSE)) {
            pthread_t tid = 0;
            pthread_create(&tid, NULL, Process_Thread, client);
        } else {TcpClient_Del(client);
        }
    }

    printf("%s - Thread Exit : %p\n", __FCUNTION__, arg);
    g_status = STOP;
}

申请响应流程

通信流程

static void DoResp(TcpClient *client)
{int len = TcpClient_Available(client);
    if (len > 0) {char *buf = malloc(len + 1);
        TcpClient_RecvRaw(client, buf, len);
        buf[len] = 0;
        char resp[255] = {0};
        // do process to create response
        TcpClient_SendRaw(client, resp, strlen(resp));
        TcpClient_Del(client);
        free(buff);
    }
}

编程试验:实现申请响应

main.c

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <time.h>
#include <fcntl.h>
#include <string.h>

#include "tcp_server.h"
#include "tcp_client.h" 
#include "utility.h"

#define BUF_SIZE 512

typedef struct {
    const char *cmd;
    void (*handler)(const char *);
}Handler;

enum {STOP, RUN, PAUSE};

static const volatile char *g_root = NULL;
static volatile int g_status = STOP;

static void DoResp(TcpClient *client)
{int len = TcpClient_Available(client);

    if (len > 0) {char *buf = malloc(len + 1);
        len = TcpClient_RecvRaw(client, buf, len);
        if (len > 0) {buf[len] = 0;
            printf("%s - Request : %s\n", __FUNCTION__, buf);
    
            char resp[255] = {0};
            sscanf(buf, "GET %s HTTP\n", resp);  // 提取文件门路!!printf("%s - Req String: %s\n", __FUNCTION__, resp);

            char* format = "HTTP/1.1 200 OK\r\n"
                "Server:D.T. Http Server\r\n"
                "Content-Length:%d\r\n"
                "Content-Type:text/html\r\n"
                "Connection:close\r\n"
                "\r\n"
                "%s";
                       
            sprintf(resp, format, strlen((const char*)g_root), g_root);
            
            TcpClient_SendRaw(client, resp, strlen(resp));
            
            TcpClient_Del(client);
        }
        free(buf);
    }
}

static void *Process_Thread(void *arg)
{while (TcpClient_IsValid(arg)) {DoResp(arg);
    }

    printf("%s - Thread Exit : %p\n", __FUNCTION__, arg);

    return arg;
}

static void *Server_Thread(void *arg)
{while (TcpServer_IsValid(arg)) {TcpClient *client = TcpServer_Accept(arg);
        if (client && (g_status != PAUSE)) {
            pthread_t tid = 0;
            pthread_create(&tid, NULL, Process_Thread, client);
        } else {TcpClient_Del(client);
        }
    }

    g_status = STOP;

    return arg;
}

static void Start_Handler(const char *arg)
{
    int err = 0;

    if (g_status == STOP) {TcpServer *server = TcpServer_New();
        TcpServer_Start(server, 9000, 100);

        if (TcpServer_IsValid(server)) {
            pthread_t tid = 0;
            err = pthread_create(&tid, NULL, Server_Thread, server);
        } else {err = 1;}
    }

    if (!err) {
        g_status = RUN;

        printf("Server is OK!\n");
    } else {
        g_status = STOP;

        printf("Server is failed!\n");
    }
}

static void Pause_Handler(const char *arg)
{if (g_status == RUN) {
        g_status = PAUSE;

        printf("Server is paused!\n");
    } else {printf("Server is NOT started!\n");
    }
}

static void Exit_Handler(const char *arg)
{exit(0);
}

static Handler g_handler[] = {{"start", Start_Handler},
    {"pause", Pause_Handler},
    {"exit",  Exit_Handler}
};

static void Run(const char *root)
{printf("File Server Demo @ D.T.Software\n");

    g_root = root;

    while (1) {char line[BUF_SIZE] = {0};
        int i = 0;

        printf("D.T.Software @ Input >>>");

        fgets(line, sizeof(line) - 1, stdin);

        line[strlen(line) - 1] = 0;

        if (*line) {char *cmd = FormatByChar(line, ' ');
            int done = 0;

            for (i-0; i<DIM(g_handler); ++i) {if (strcmp (g_handler[i].cmd, cmd) == 0) {g_handler[i].handler(cmd);
                    done = 1;
                    break;
                }
            }

            if (!done) {printf("'\%s\' can NOT be parsed!\n", cmd);
            }

            free(cmd);
        }
    }
}

int main(int argc, char *argv[])
{if (argc >= 2) {DIR *dir = opendir(argv[1]);

        if (dir != NULL) {closedir(dir);
            Run(argv[1]);
        }
    }

    printf("Can not launch File Server, need a valid directory as roots.\n");

    return 0;
}

输入:

tiansong@tiansong:~/Desktop/network/web$ ./a.out ./
File Server Demo @ D.T.Software
D.T.Software @ Input >>> start
Server is OK!
D.T.Software @ Input >>> DoResp - Request : GET / HTTP/1.1
Host: 192.168.112.165:9000
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.50
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6


DoResp - Req String: /1/2/3  // 提取到的文件门路!!Process_Thread - Thread Exit : 0x7f77ac000c90
DoResp - Request : GET /favicon.ico HTTP/1.1
Host: 192.168.112.165:9000
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.50
Accept: image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
Referer: http://192.168.112.165:9000/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6


DoResp - Req String: /favicon.ico
Process_Thread - Thread Exit : 0x7f77ac000b20

浏览器申请

思考

favivon.ico 是什么?如何解决?

如何创立浏览器中的文件展现页面?

退出移动版